指针是C语言学习中的重点和难点
今天我们来说说指针的一部分进阶理解,对初学者很有帮助
首先我们创建一个数组
int arr[5] = {1,2,3,4,5};
大家都知道这里arr代表数组首元素1的地址
而&arr、*&arr、&*arr的意义,可能就不是显而易见了
对于类似问题,可以由以下几点逐步理解
我们先取上面数组arr的地址,存入p
int (*p) [5] = &arr;
那么此时,我们对p解引用,会得到什么?
经过编译器验证,此时*p的类型为int*,但在理解时我们却不能将*p当成简单的int*
事实上,*p的意义是整个数组
那么我们可以这样理解
数组指针解引用得到整个数组,它的实质是另一个指针变量,其指向该数组第一个元素,其类型由该数组第一个元素决定
因此**p = 1
由此我们不难解释*&arr和&*arr的区别
前者:先取整个数组的地址,然后解引用,得到整个数组
后者:先对数组首元素地址解引用,得到首元素1后,取1的地址
因此有
(32位)
(此处默认大家已掌握sizeof操作符用法)
我们先创建一个二维数组
int arr2[2][3] = {{1,2,3},{4,5,6}};
此时,arr2表示数组首元素地址,即数组{1,2,3}的地址,arr2的类型是int(*)[3]
那么,由刚刚红色段落的解释,*arr2表示{1,2,3}整个数组,他的类型是int*,指向{1,2,3}数组的第一个元素1
因此**arr2 = 1
为了加深理解,我们在这里取arr2的地址,存入p2
int (*p2) [2][3] = &arr2;
然后我们再对p2进行解引用
第一次解引用:由刚刚红色段落的解释,*p2表示整个二维数组,sizeof(*p2) = 2*3*4,*p2的类型为指向该二维数组元素的指针的类型,即int (*) [3];*p2指向该二维数组首元素
第二次解引用:由于*p2的类型为int (*) [3],参考一维数组的解引用,不难得出,**p2的类型为int*,指向数组{1,2,3}中的元素1
第三次解引用:***p2 = 1;
我们先举三维数组的例子
int arr3[2][3][4];
我们可以将arr3理解为{A1,A2}
其中A1,A2为类型为int[3][4]的数组
我们继续进行类似的操作
int (*p3)[2][3][4] = &arr3;
1.*p3表示整个三维数组, sizeof(*p3) = 2*3*4*4;*p3的类型为指向该数组首元素指针的类型,即指向A1的指针的类型,为int (*)[3][4]
2.由于*p3指向数组A1,那么*(*p3)表示整个二维数组A1,**p3类型为int (*)[4]
3.***p3类型为int*
4.****p3 = 该三维数组内第一个整数
由三维数组,不难得出多维数组指针解引用的规律
综上,我们可以看出
若a的类型是(int (*)[3][4][5]),*a,类型是:int (*)[4][5]
若a的类型是(int (*)[4][5]),*a,类型是:int (*)[5]
若a的类型是(int (*)[5]),*a,类型是:int*
由此可得出,当一个数组指针s的类型为 int (*)[x1][x2]……[xn](n>1)时
*s的类型为 int (*)[x2][x3]……[xn]