首先从一个例子入手:
a[3][5]={{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15}};
a的数组元素是按行存储的,那么可以将a数组的三行看成3个分数组:a[0],a[1],a[2] 。
每一个行中都是存储了5个列元素的一维数组。
其中,数组名a是指向0号分数组的指针常量 , a+1 a+2则是指向1号分数组和2号分数组的指针常量。
a[0],a[1],a[2]是三个分数组的数组名,这三个数组名又是指向各分数组0号元素a[0][0],a[1][0],a[2][0]的指针常量。
而a[0]+1,a[0]+2,则是指向a[0][1],a[0][2]的指针常量。
数组元素中的 “ [ ] ”是变址运算符,相当于 *( + )。
所以
b[ j ]相当于 *(b + j )。
对二维数组a[ i ][ j ],将分数组名a[ i ]当作b代入*( b + j ),
得到 *( a[ i ] + j )。
再将a[ i ]换成*( a + i ),
得到( ( a + i ) + j )。
a[ i ][ j ];
*( a[ i ] + j );
*(*( a + i ) + j); // 三者相同,都是表示第i行,第j列元素。
eg:
int a[2][2]={2,0,4,8};
printf("%d\n",**a);
printf("%d\n",**a+1);
printf("%d\n",*(*a+1));
printf("%d\n",**(a+1));
现在根据以上模板就可以了解清楚以上代码的具体含义啦
如果对指针还不太熟练,可以先将他们改写成数组模式。
如
**( a + 1 ) = *( *( a + 1 ) + 0 ) = *( a[ 1 ] + 0 ) = a[ 1 ][ 0 ];
然后 我们讨论下 数组名与指针的关系
表示形式 | 含义 | 内容 |
---|---|---|
a,&a[0] | 二维数组名,0行分数组的地址 | 65470 |
a[0],*a, &a[0][0] | 0行分数组名,0行0列元素的地址 | 65470 |
a[0]+1,*a+1,&a[0][1] | 0行1列数组的地址 | 65472 |
a+1,&a[1] | 1行分数组的地址 | 65480 |
a[1],*(a+1),&a[1][0] | 1行分数组名,1行0列元素的地址 | 65480 |
a[1]+3,,*(a+1)+3,&a[1][3] | 1行3列元素的地址 | 654486 |
*(a[3]+2), *(*(a+3)+2),a[3][2] | 第3行2列元素 | 14 |
a和a[0]的地址字节都是65470但不等价,他们的基类型字节数不同。
可以从a+1 和 a[0]+1 地址字节值不同得到证实。
从以上表格比较可知道,多维数组名并不是指向整个多维数组的指针,而是指向0号分数组的指针。
同理,一维数组名也不是指向整个一维数组的指针,而是指向0号数组元素的指针。
所以,可以统称数组名是指向0号分量的指针。