MENU

用指针访问二维数组

January 13, 2019 • 我爱学习

在日常做题的过程中,发现了一个关于通过指针访问二维数组的问题

题目如下:

**若有以下语句:
**int a[4][5],(*p)[5];
p=a;
`下面哪个选项表示a数组中的元素?
`A.  p+1
B. * (p+3)
C. * (p+1)+3
D. ( p+2)`

正确答案为D,我选择了B项。

以下是我的想法 (注意!!这只是我自己错误的思路!!!)

由题干可得:

开了一个4行5列名为a的二维数组,同时声明了一个大小为5的数组指针。

此时p中存着数组a的首地址,即指针p指向a[0][0],即(*p)== a[0][0] 。

因此B项中,*(p + 3) 等价于 a[0][3] (此处我的思路开始出错,原因是没有理解指针表示二维数组时的原理)

所以我认为B项为正确答案;

正确思路:

由题干可得:

开了一个4行5列名为a的二维数组,同时声明了一个大小为5的数组指针。

此时p中存着数组a的首地址,即指针p指向a[0][0],即(*p)== a[0][0] 。

此时,首先来了解一下指针表示二维数组时的原理:

假如有一个二维数组:
int a[3][4] = {{1, 3, 5, 7}, {9, 11, 13, 15}, {17, 19, 21, 23}}; 
        其中,a 是二维数组名。a 数组包含 3 行,即 3 个行元素:a[0],a[1],a[2]。每个行元素都可以看成含有 4 个元素的一维数组。而且 C 语言规定,a[0]、a[1]、a[2]分别是这三个一维数组的数组名。

        a[0]、a[1]、a[2] 既然是一维数组名,一维数组的数组名表示的就是数组第一个元素的地址,所以 a[0] 表示的就是元素 a[0][0] 的地址,即 a[0]&a[0][0];a[1] 表示的就是元素 a[1][0] 的地址,即 a[1]&a[1][0];a[2] 表示的就是元素 a[2][0] 的地址,即 a[2]==&a[2][0]。

        所以二维数组a[M][N]中,a[i]表示的就是元素a[i][0]的地址,即a[i] == &a[i][0] ;我们知道,在一维数组 b 中,数组名 b 代表数组的首地址,即数组第一个元素的地址,b+1 代表数组第二个元素的地址,…,b+n 代表数组第 n+1 个元素的地址。所以既然 a[0]、a[1]、a[2]、…、a[M–1] 分别表示二维数组 a[M][N] 第 0 行、第 1 行、第 2 行、…、第 M–1 行各一维数组的首地址,那么同样的道理,a[0]+1 就表示元素 a[0][1] 的地址,a[0]+2 就表示元素 a[0][2] 的地址,a[1]+1 就表示元素 a[1][1] 的地址,a[1]+2 就表示元素 a[1][2] 的地址……a[i]+j 就表示 a[i][j] 的地址,即a[i]+j == &a[i][j]&a[i][0]+j == &a[i][j]

        又因为在一维数组中 a[i] 和 *(a+i)  等价,即a[i] == *(a+i)这个关系在二维数组中同样适用,二维数组 a[M][N] 就是有 M 个元素 a[0]、a[1]、…、a[M–1] 的一维数组。所以可得*(a+i)+j == &a[i][j]

至此,我们可以理解为什么B项是错误的。

那么为什么要选D呢?

        二维数组可以想象成一个一维数组,二维数组 a[3][4] 就是有三个元素的一维数组,同时,这三个元素又各是一个一维数组 (为了方便理解,此处一位数组命名为t)t[0]、t[1]、t[2] (通俗来讲就是两个一维数组的嵌套)。所以数组 a 的第一个元素不是 a[0][0],而是 t[0],所以数组名 a 表示的不是元素 a[0][0] 的地址,而是 t[0] 的地址,而t[0]表示的是一维数组t的第一个元素。

所以由此可得:

a == &a[0];
又
a[0] == &a[0][0];

综合上面两个结论,得出:

*(p + 2)  ==  &a[2][0];
*(*(p + 2)) == a[2][0];

 所以选D项。

结束。

Last Modified: September 8, 2021