多维数组可以看成是数组的数组,我们将声明一个数组,以此来探究指针与多维数组的联系和表示,这是需要认真的揣摩和分析。假设有如下声明:
int array[4][2]; /*整数数组的数组*/
数组名array是数组首元素的地址,在本例中,array的首元素本身包含两个int的数组,因此array也是包含两个int的数组的地址。下面从指针属性进一步分析:
(1)因为array是数组首元素的地址,所以array的值和&array[0]相同。另一方面,array[0]本身是包含两个整数的数组,因此array[0]的值同其首元素(一个整数)的地址&array[0][0]相同。简单地说,array[0]是一个整数大小对象的地址,而array是两个整数大小对象的地址。array和array[0]开始于同一个地址,因此array和array[0]具有相同的数值。
(2)对一个指针(也即地址)加1,会对原来的数值加上一个对应类型大小的数值。array所指对象的大小是两个int,而array[0]所指对象的大小是一个int。因此array和array[0]+1的结果不同。
(3)对一个指针(也即地址)取值(使用运算符*或者带有索引的[]运算符)得到的是该指针所指向对象的数值。因为array[0]是其首元素array[0][0]的地址,所以*(array[0])代表存储在array[0][0]中的数值,即一个int数值。同样,array是地址的地址,需要两次取值才可以得到通常的数值。*array是array[0],而array[0]又是&array[0][0],因此*array是&array[0][0],**array[0][0]等价于*(&array[0][0]),即为一个int数array[0][0]。
#include <stdio.h>
int main(void)
{
int array[4][2] = {{2, 4}, {6, 8}, {1, 3}, {5, 7}};
printf(" array = %p, array + 1 = %p\n", array, array +1);
printf("array[0] = %p, array[0] + 1 = %p\n", array[0], array[0] + 1);
printf(" *array = %p, *array + 1 = %p\n", *array, *array + 1);
printf("array[0][0] = %d\n", array[0][0]);
printf(" *array[0] = %d\n", *array[0]);
printf(" **array = %d\n", **array);
printf(" array[2][1] = %d\n", array[2][1]);
printf("* (* (array+2) + 1) = %d\n", * (* (array+2) + 1));
return 0;
}
注:每台电脑上运行的地址结果可能不一样,但是各地址间的差值是一样的,
比如第一条地址运行结果,十六进制0x98-0x90的结果(9*16 +8 - 9*16)=8个字节,
即两个int整数。因此,我们可以根据结果来更进一步认识指针与多维数组。
输出显示出二维数组array的地址和一位数组array[0]的地址是相同的,
均为相应的数组首元素的地址,它的值是和&array[0][0]相同的。
二维数组名必须两次取值才可以取出数组中存储的数据。这两次可以使用间接运算符(*)来实现,或两次使用方括号运算符([])来实现。具体地:array[2][1]的等价指针符号表示为*(*(array+2)+1)。
分析*(*(array+2)+1)
显示了二维数组地址、数组内容和指针之间的关系