使用二维数组来探究诸如&a[][] ,*((a+1)+3)此类数组指针的关系
#include<stdio.h>
int main()
{
int a[3][5]={{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15}};
printf("a=%p\n",a); //a为二维数组名
printf("&a[0]=%p\n",&a[0]); //&a[0] 数组首元素a[0]的地址 和上面的a含义相同
//a[0] *(a+0) *a &a[0][0] 均为a[0][0]元素的地址,四者含义相同
printf("a[0] = %p ,*(a+0) = %p , *a=%p ,&a[0][0]=%p\n",a[0],*(a+0),*a,&a[0][0]);
//a[0]+1 *a+1 &a[0][1] 均为a[0][1]元素的地址,三者的含义相同
printf("a[0]+1=%p, *a+1=%p , &a[0][1]=%p \n",a[0]+1,*a+1,&a[0][1]);
//a+1 &a[1] 均为a+1的地址,两者含义相同
printf("a+1=%p , &a[1]=%p\n",a+1,&a[1]);
//a[1] *(a+1) a[1][0] 均为a[1][0]元素的地址,三者的含义相同
printf("a[1]=%p, *(a+1)=%P, a[1][0]=%p\n",a[1],*(a+1),&a[1][0]);
//a[1]+4 *(a+1)+4 &a[1][4] 均为a[1][4]元素的地址,三者的含义相同
printf("a[1]+4=%p, *(a+1)+4=%p, &a[1][4]=%p\n",a[1]+4,*(a+1)+4,&a[1][4]);
//*(a[2]+4) *(*(a+2)+4) a[2][4] 均为a[2][4]元素,三者的含义相同
printf("*(a[2]+4)=%d, *(*(a+2)+4)=%d, a[2][4]=%d\n",*(a[2]+4),*(*(a+2)+4),a[2][4]);
return 0;
}
总结:
数组名 a 实际可以看成为一维数组a{ {},{},{}},含义为其第一个元素的首地址,即&a[0]
*a 理解为对 a{ {},{},{}}这个一维数组的第一个元素(数组元素a[0])进行解引用,获得的是a[0][0]的地址。
a[n] 已经是 数组a第n+1个元素(数组元素a[n])的第一个元素 a[n][0] 的地址
*a[n] 表示 a{ {},{},{}} 这个一维数组的第 n+1个元素(数组元素a[n])的地址 , 步长实际为二维数组a下的一个一维数组。
&a 表述为 整个数组的地址
&a[n] 表示 a[n] 的地址,即a{ {},{},{}}这个一维数组第n+1个元素的地址
注:*a[x][y]这种写法是不可取的,会提示illegal indirection,不合法的引用。因为a[x][y]已经是一个数据值了,对值进行解引用一定是不合法的。
其实我们也可以把 "[]" 这种变址符号理解为一次特殊的解引用。
而使用‘&’取地址和使用‘*’解引用的方法可以跟高数中的 求导 与 积分对比理解记忆。
'& ' 寻址溯源 可以理解为一次 积分 而 ' *' 据址寻值 可以理解为一次 求导。