数组的名字代表了此数组的首地址,对数组再取地址,它的值仍是相同的。
int a[5] = {1,2,3,4,5}; a ,&a 它们的值是相同的
对数组取地址,类型可以当做指向此种数组的指针来使用,这里没有确定说它是指针
int a[5] = {1,2,3,4,5};
&a 类型当做为指向一维数组(5个元素)的指针,即 int (*)[5]
于是 &a+1 的数据为a的地址 + 5*sizeof(int)
int b[3][4] = { {1,2,3,4}, {5,6,7,8}, {9,10,11,12}};
&b 类型当做为指向二维数组(3*4个元素)的指针,即 int (*)[3][4]
&b+1 的数据为b的地址 + 3*4*sizeof(int)
这里没有说 &数组 就是指针,因为再 &(&数组名) 或 &(&(&数组名) ) ,它们与 数组名的值都是一样,显然指针是没有这种特性的
指向数组的指针的解引用
三维数组,可以看做是指向二维数组的指针,解引用后为指向一维数组的指针,即二维数组
二维数组,可以看做是指向一维数组的指针,解引用后为指向类型(如int)的指针,即一维数组
一维数组,可以看做是指向类型(如int)的指针,解引用后为类型数(如int数),即一个数
{
int a[ 5 ] = { 1 , 2 , 3 , 4 , 5 };
int b[ 3 ][ 4 ] = { { 1 , 2 , 3 , 4 }, { 5 , 6 , 7 , 8 }, { 9 , 10 , 11 , 12 }};
printf( " %p/n " , & a); /* a取地址(类型当做指向一维数组(有5个元素)的指针 ,即int (*)[5] ) ,对数组取地址,内容与数组的首地址相同 ,记为 pA */
printf( " %p/n " , & a + 1 ); /* pA + 5*sizeof(int) ,&a指向一维数组,加1则跳过5个元素 */
printf( "/n " );
printf( " %p/n " ,a); /* a的值(数组a的首地址, 类型当做是 int *) 以地址形式打印 值仍为 pA */
printf( " %p/n " ,a + 1 ); /* pA + 1*sizeof(int) , a指向int , 加1跳过1个元素 */
printf( "/n " );
printf( " %p/n " , & b); /* b取地址(类型当做指向二维数组(有3*4个元素)的指针 ,即int (*)[3][4] ) ,对数组取地址,内容与数组的首地址相同 ,记为 pB */
printf( " %p/n " , & b + 1 ); /* pB + 3*4*sizeof(int) ,&b指向二维数组,加1则跳过3*4个元素 */
printf( "/n " );
printf( " %p/n " ,b); /* b的值 (数组b的首地址, 类型看做是 int (*)[4] ) 以地址形式打印 值仍为 pB */
printf( " %p/n " ,b + 1 ); /* pB + 4*sizeof(int), b指向一维数组(4个元素) ,加1跳过4个元素 */
printf( "/n " );
printf( " %p/n " , * b); /* 二维数组解引用为一维数组 *b == *(b+0) == b[0] */
printf( " %p/n " , * b + 1 ); /* 一维数组加1, 跳过1个元素 ,即 加上 1*sizeof(int) */
printf( "/n " );
printf( " %p/n " , ** b); /* 一维数组解引用为一个类型数 **b == *(*(b+0) +0) == *(b[0] +0) == b[0][0] */
printf( " %p/n " , ** b + 1 ); /* b[0][0]+1 == 2 */
getch();
return 0 ;
}
结果如下
int c[3][4][5];
&c的类型是(int(*)[3][4][5])
c的类型是(int(*)[4][5]),
*c,即c[0], 类型是int(*)[5]
*c[0]类型是int*
数组做为形参时,退化为指针
三维数组,退化为指向二维数组的指针
二维数组,退化为指向一维数组的指针
一维数组,退化为指向类型(如int)的指针
可以用下面函数做测试,注意,数组做为参数时,只有第一个维数可以为空,其他的必须填写
如参数可以是 int ss[][4] 或 int ss[2][3] ,int ss[][4][5]
test(int ss[][4])
{
printf("%p/n",ss);
printf("%p/n",ss+1);
}