IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C-指针与数组 -> 正文阅读

[C++知识库]C-指针与数组

目录

目录

1,指针与一维数组,sizeof和strlen操作

2,二维数组,sizeof操作

3,指针类型转换及解引用


1,指针与一维数组,sizeof和strlen操作

//一维数组
int a[] = {1,2,3,4}; 
      
printf("%d\n",sizeof(a));     //16,sizeof直接操作数组名,数组名代表整个数组,sizeof(a)是整个数 
                              //组的大小
printf("%d\n",sizeof(a+0));   //4,a+0代表首元素的地址
printf("%d\n",sizeof(*a));    //4,*a代表首元素
printf("%d\n",sizeof(a+1));   //4,a+1代表第二个元素的地址
printf("%d\n",sizeof(a[1]));  //4,a[1]代表首元素
printf("%d\n",sizeof(&a));    //4,&a代表整个数组的地址
printf("%d\n",sizeof(*&a));   //16,*&a代表整个数组
printf("%d\n",sizeof(&a+1));  //4,&a+1代表跳过整个数组的地址
printf("%d\n",sizeof(&a[0])); //4,&a[0]代表取首元素的地址
printf("%d\n",sizeof(&a[0]+1)); //4,&a[0]+1代表第二个元素的地址

上述代码中,对int类型数组进行sizeof操作;

注意:一般情况下数组名代表首元素的地址,但有两种特殊情况,1:sizeof(数组名),此时代表计算整个数组的占用空间大小,此时数组名代表整个数组,而不是数组元素的首地址;2,&数组名,此时代表取这个数组的地址。

//字符数组
char arr[] = {'a','b','c','d','e','f'};

printf("%d\n", sizeof(arr));        //6,sizeof直接操作数组名,arr代表整个数组
printf("%d\n", sizeof(arr+0));      //4,arr+0代表第一个元素的地址
printf("%d\n", sizeof(*arr));       //1,*arr代表第一个元素
printf("%d\n", sizeof(arr[1]));     //1,arr[1]代表第一个元素
printf("%d\n", sizeof(&arr));       //4,&arr代表整个数组的地址
printf("%d\n", sizeof(&arr+1));     //4,&arr+1代表跳过整个数组的地址
printf("%d\n", sizeof(&arr[0]+1));  //4,&arr[0]+1代表第二个元素的地址


printf("%d\n", strlen(arr));        //随机值,从arr数组的首地址往后查找,直到找到\0
printf("%d\n", strlen(arr+0));      //随机值,从arr数组的首地址往后查找,直到找到\0
printf("%d\n", strlen(*arr));       //error,*arr是字符'a',从对应的ascii码的地址处查找
printf("%d\n", strlen(arr[1]));     //error,*arr是字符'b',从对应的ascii码的地址处查找
printf("%d\n", strlen(&arr));       //随机值,从arr数组的地址往后查找,直到找到\0
printf("%d\n", strlen(&arr+1));     //随机值,从跳过arr数组的地址往后查找,直到找到\0
printf("%d\n", strlen(&arr[0]+1));  //随机值,从第二个元素的地址处开始查找,直到找到\0

?上述代码中,对char[]类型数组进行sizeof和strlen操作,注意strlen的查找原理是从首地址往后查找,直到找到\0,strlen函数的参数类型是const char * str,因此strlen(&arr)会报错,因为&arr的数据类型是char(*p)[ ],但程序能够运行得到结果。

char arr[] = "abcdef";

printf("%d\n", sizeof(arr));       //7,默认此种数组写法最后还有\0
printf("%d\n", sizeof(arr+0));     //4,arr+0第一个元素的地址
printf("%d\n", sizeof(*arr));      //1,*arr代表第一个元素
printf("%d\n", sizeof(arr[1]));    //1,arr[1]代表第二个元素
printf("%d\n", sizeof(&arr));      //4,&arr代表整个数组的地址
printf("%d\n", sizeof(&arr+1));    //4,&arr+1代表跳过arr数组的地址
printf("%d\n", sizeof(&arr[0]+1)); //4,&arr[0]+1代表第二个元素的地址

printf("%d\n", strlen(arr));       //6,从arr数组的地址开始查找,直到找到\0
printf("%d\n", strlen(arr+0));     //6,从arr数组的首元素地址开始查找,直到找到\0
printf("%d\n", strlen(*arr));      //error,*arr代表字符'a',从对应的ascii码的地址处查找
printf("%d\n", strlen(arr[1]));    //error,*arr代表字符'b',从对应的ascii码的地址处查找
printf("%d\n", strlen(&arr));      //6,从arr数组的地址开始查找,直到找到\0
printf("%d\n", strlen(&arr+1));    //随机值,从跳过arr数组的地址处开始查找,直到找到\0
printf("%d\n", strlen(&arr[0]+1)); //5,从arr数组的第二个元素地址开始查找,直到找到\0 

?注意char arr[] = "abcdef"与char arr[] = {'a','b','c','d','e','f'};两种字符数组表示方法的区别,第一种默认字符中存在\0。

char *p = "abcdef";

printf("%d\n", sizeof(p));       //4,p是指针,存放的数组首元素的地址
printf("%d\n", sizeof(p+1));     //4,p+1存放的数组第二个元素的地址
printf("%d\n", sizeof(*p));      //1,*p代表数组首元素
printf("%d\n", sizeof(p[0]));    //1,p[0]代表数组首元素,与*p效果一样
printf("%d\n", sizeof(&p));      //4,&p是存放指针p的地址
printf("%d\n", sizeof(&p+1));    //4,&p+1是地址,跳过p的地址
printf("%d\n", sizeof(&p[0]+1)); //4,&p[0]+1代表第二个元素的地址

printf("%d\n", strlen(p));       //6,P是数组首元素的地址,从此地址处往后查找,直到找到\0
printf("%d\n", strlen(p+1));    //5,P是数组第二个元素的地址,从此地址处往后查找,直到找到\0
printf("%d\n", strlen(*p));     //error,*p代表'a',从对应的ascii码的地址处查找
printf("%d\n", strlen(p[0]));   //error,*p代表'a',从对应的ascii码的地址处查找
printf("%d\n", strlen(&p));     //随机值
printf("%d\n", strlen(&p+1));   //随机值
printf("%d\n", strlen(&p[0]+1));//5,&p[0]+1代表数组第二个元素的地址

注意对于指向数组的指针p,*(p+i)与p[i]效果一样。

2,二维数组,sizeof操作

//二维数组
int a[3][4] = {0};

printf("%d\n",sizeof(a));        //48,a代表整个数组
printf("%d\n",sizeof(a[0][0]));  //4,a[0][0]代表第一行第一个元素
printf("%d\n",sizeof(a[0]));     //16,a[0]是数组名,sizeof直接作用于数组名时,代表整个数 
                                 //组,即第一行的元素
printf("%d\n",sizeof(a[0]+1));   //4,a[0]+1代表第一行第二个元素的地址
printf("%d\n",sizeof(*(a[0]+1)));//4,*(a[0]+1)代表第一行第二个元素
printf("%d\n",sizeof(a+1));      //4,代表数组第二行的地址
printf("%d\n",sizeof(*(a+1)));   //16,数组第二行所占空间大小
printf("%d\n",sizeof(&a[0]+1));  //4,代表数组第二行的地址
printf("%d\n",sizeof(*(&a[0]+1))); //16,数组第二行所占空间大小
printf("%d\n",sizeof(*a));         //16,数组第一行所占空间大小
printf("%d\n",sizeof(a[3]));       //16,虽然数组实际中不存在第三行,但sizeof中不会进行真正 
                                   //的计算,只会根据数组的类型判断,也就是会判断a[3]是数组 
                                   //名,sizeof(数组名)代表整个数组的大小

对于二维数组,数组的首地址是第一行。?

3,指针类型转换及解引用

int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int *ptr = (int *)(&a + 1);
printf( "%d,%d", *(a + 1), *(ptr - 1));
return 0;
}

?&a+1表示跳过整个数组的地址,(int *)(&a + 1)表示对对这个地址强制转换为int* ptr,*(ptr - 1)表示指针减1后解引用。

struct Test
{
int Num;
char *pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{
printf("%p\n", p + 0x1);
printf("%p\n", (unsigned long)p + 0x1);
printf("%p\n", (unsigned int*)p + 0x1);
return 0;
}

?不同类型的指针加减操作的结果。

int main()
{
int a[4] = { 1, 2, 3, 4 };
int *ptr1 = (int *)(&a + 1);
int *ptr2 = (int *)((int)a + 1);
printf( "%x,%x", ptr1[-1], *ptr2);
return 0;
}

?ptr1[-1]等价于*(ptr1-1),(int)a + 1将数组a的首元素地址转换为int后加1,相当于指向的地址移动了一个字节,x%代表以16进制形式输出。

#include <stdio.h>
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
int *p;
p = a[0];
printf( "%d", p[0]);
return 0;
}

?int a[3][2] = { (0, 1), (2, 3), (4, 5) };数组的中括号表达式的值最后一个数值,因此此数组是

?int a[3][2] = { 1, 3?,5},空的位置补0,a[0]代表首行数组的数组名,数组名代表首元素地址,因此指针p指向第一行的第一个元素,因此p[0]的值为1。

int main()
{
int a[5][5];
int(*p)[4];
p = a;
printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
return 0;
}

指针变量p的类型为int(*)[4],数组int a[5][5]的数组名a是数组首元素的地址,二维数组首元素是第一行,因此a的数据类型为int(*)[5],当将a赋给p时,因为数据类型不匹配,会有警告。&p[4][2] 和?&a[4][2]所指向的地址如下图所示,可看到他们相差四个字节,第一次使用p%打印时打印的是-4在内存中存储的补码,第二次打印时打印的是-4。注意&p[4][2]中,p[4]等价于*(p+4),得到的是一个一维数组,然后取这个一维数组中的第三个元素的地址,&p[4][2]等价于&(*(*(p+4)+2))。

int main()
{
int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int *ptr1 = (int *)(&aa + 1);
int *ptr2 = (int *)(*(aa + 1));
printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1));
return 0;
}

?&aa是取整个数组的地址,&aa+1是跳过整个数组的地址,int*将其强制转换类型;

aa是数组名,代表首元素的地址,二维数组的首元素是首行,所以aa代表的是首行的地址,aa+1跳过首行的地址,*(aa+1)得到的是第二行的数组名,数组名是首元素的地址。

#include <stdio.h>
int main()
{
char *a[] = {"work","at","alibaba"};
char**pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}

?一个字符类型指针指向字符串的表达形式为,char* p = "work";

因此 char *a[] = {"work","at","alibaba"};代表将三个字符串的首元素地址放到数组指针a中,然后又将数组a的首元素地址放到pa中,pa++指向a中第二个元素的地址,*pa获取数组a中存放的第二个元素,它存储的是字符"at"的首元素地址,s%打印得到at。

int main()
{
char *c[] = {"ENTER","NEW","POINT","FIRST"};
char**cp[] = {c+3,c+2,c+1,c};
char***cpp = cp;
printf("%s\n", **++cpp);
printf("%s\n", *--*++cpp+3);
printf("%s\n", *cpp[-2]+3);
printf("%s\n", cpp[-1][-1]+1);
return 0;
}

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-08-19 18:45:50  更:2022-08-19 18:47:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/10 5:42:31-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码