数组名+1和&数组名+1的区别

一、数组名的含义

首先理解 首元素地址数组的首地址 两个概念。

首元素地址,即数组第一个元素的地址;数组的首地址,即整个数组的首地址。二者在值上是相等的(因为数组的首地址也是从第一个元素开始的),但是二者的含义是不同的。

比如首元素地址加 1 ,即表示第二个元素的地址,期跨度为一个元素所占的字节;而数组的首地址加 1 ,其跨度为整个数组,如果 int a[5] ,那么跨度就是 4*5 = 20 ,即地址会加 20 个字节。

1、一维数组
int array_1[6] = {0};//数组名array_1 含义为指向这个一维数组的 首元素的地址 

一维数组的数组名表示数组首元素的地址(区别于数组的首地址)。它是一个指向第一个元素的指针常量。正因为是常量,所以array_1 ++ 就是一个错误的表达,常量不存在 + + 操作,所以要想访问第二个元素,需要 array_1+1 来实现。

2、二维数组

二维数组常规理解为行和列,这里换个角度看待二维数组。

二维数组看成是一个一维数组,然后这个一维数组的每个元素都是由另一个一维数组组成。

int array_2[2][4] = {0};/* (1)二维数组实际上就是元素为一维数组的数组(2)二维数组名可以看做指向其第一个元素(一维数组)的指针*/

把array_2看成是一个有两个元素组成的一维数组,然后这个一维数组的两个元素都是由四个元素的一维数组组成。这边把第一个一维数组称为第一维数组,第二个一维数组称为第二维数组

array_2表示第一维数组的数组名,所以其是指向第一维数组的首元素的。

array_2[0]、array_2[1] 分别表示两个第二维数组的数组名,它们的长度都是4。将array_2[0]、array_2[1] 当做整体来看待,例如a[4]、b[4] 为两个一维数组,这里将 a 当成 array_2[0],将 b当成 array_2[1]。

综上,二维数组的数组名,实际上是指向第一维数组的首元素的指针,而这个首元素的内容为第二维数组的首元素地址,即,*array_2 与 array_2[0] 是等价的( * 表示解引用,所以此处 *array_2 表示的是第一维数组的首元素的内容,这个内容是指向第二维数组的首元素;array_2[0] 为第二维数组的数组名,所以 array_2[0] 也是指向第二维数组的首元素)( *array_ 2 + 1 等价于 array_2[0] + 1,可自行验证)。
所以二维数组的数组名是指向指针的指针常量,类似于二重指针。

3、三维数组及多维数组

三维及以上数组,和二维数组类似的分析,不再赘述。

二、&数组名的含义

对数组名取地址所产生的值的类型是一个指向整个数组的指针,而不是一个指向指针常量的指针。所以&array的类型是指向整个数组的指针,而array是指向array[0]的指针,虽然在数值上相同,但是在类型上不同。

正因为它们的类型不同,所以在加1或减1的时候,颗粒度不同。array以一个数组元素为颗粒度,以 int array[5] = {0} 为例,例子中的数组元素为整型,所以array加1时地址加4;而&array以整个数组为颗粒度,例子中的数组为有5个元素的整型数组,所以&array加1时,地址加20。&a 是整个数组的首地址,a是数组首元素的首地址,其值相同但意义不同。

三、具体运行结果

/******一维数组******/ short int array_1[6] = {0};printf("///******一维数组******///\t"); printf("short int array_1[6] = {0};\t");printf("(1)array_1 = %d\t", array_1); printf("(2)array_1 + 1 = %d\t", array_1 + 1);printf("(3) &array_1 = %d\t", &array_1); printf("(4) &array_1 + 1 = %d\t", &array_1 + 1);putchar('\n');printf("(5) array_1[0] = %d\t", array_1[0]); printf("(6) array_1[0] + 1 = %d\t", array_1[0] + 1);printf("(7)&array_1[0] = %d\t", &array_1[0]); printf("(8)&array_1[0] + 1 = %d\t", &array_1[0] + 1);putchar('\n');
/******二维数组******/ short int array_2[2][4] = {0};printf("///******二维数组******///\n");printf("short int array_2[2][4] = {0};\n");printf("(1)array_2 = %d\n", array_2);printf("(2)array_2 + 1 = %d\n", array_2 + 1);printf("(3) &array_2 = %d\n", &array_2);printf("(4) &array_2 + 1 = %d\n", &array_2 + 1);printf("(5) array_2[0] = %d\n", array_2[0]);printf("(6) array_2[0] + 1 = %d\n", array_2[0] + 1);printf("(7)&array_2[0] = %d\n", &array_2[0]);printf("(8)&array_2[0] + 1 = %d\n", &array_2[0] + 1);printf("(9) array_2[0][0] = %d\n", array_2[0][0]);printf("(10)array_2[0][0] + 1 = %d\n", array_2[0][0] + 1);printf("(11) &array_2[0][0] = %d\n", &array_2[0][0]);printf("(12) &array_2[0][0] + 1 = %d\n", &array_2[0][0] + 1);
/******三维数组******/short int array_3[2][3][4] = {0};printf("\n///******三维数组******///\n"); printf("short int array_3[2][3][4] = {0};\n");printf("(1)array_3 = %d\n", array_3);printf("(2)array_3 + 1 = %d\n", array_3 + 1);printf("(3) &array_3 = %d\n", &array_3);printf("(4) &array_3 + 1 = %d\n", &array_3 + 1);putchar('\n');printf("(5) array_3[0] = %d\n", array_3[0]);printf("(6) array_3[0] + 1 = %d\n", array_3[0] + 1);printf("(7)&array_3[0] = %d\n", &array_3[0]);printf("(8)&array_3[0] + 1 = %d\n", &array_3[0] + 1);putchar('\n');printf("(9)array_3[0][0] = %d\n", array_3[0][0]);printf("(10) array_3[0][0] + 1 = %d\n", array_3[0][0] + 1);printf("(11)&array_3[0][0] = %d\n", &array_3[0][0]);printf("(12)&array_3[0][0] + 1 = %d\n", &array_3[0][0] + 1);putchar('\n');printf("(13)array_3[0][0][0] = %d\n", array_3[0][0][0]);printf("(14)array_3[0][0][0] + 1 = %d\n", array_3[0][0][0] + 1);printf("(15) &array_3[0][0][0] = %d\n", &array_3[0][0][0]);printf("(16) &array_3[0][0][0] + 1 = %d\n", &array_3[0][0][0] + 1);

注:以上均用的 short int 类型,即一个元素占 2 个字节。
结果如下: