这个说法有道理吗,出自书C Programming: A Modern Approach, 2nd Edition第 269 页
Just as the name of a one-dimensional array can be used as a pointer, so can the name of any array, regardless of how many dimensions it has. Some care is required, though. Consider the following array:
int a[NUM_ROWS][NUM_COLS];
a
is not a pointer toa[0][0];
instead, it's a pointer toa[0]
. This makes more sense if we look at it from the standpoint of C, which regardsa
not as a two-dimensional array but as a one-dimensional array whose elements are one-dimensional arrays. When used as a pointer,a
has typeint (*) [NUM_COLS]
(pointer to an integer array of lengthNUM_COLS
).
我很困惑,因为当我想到“其元素是一维数组的数组”时,我想到了一个jagged-array ,但这不是这里发生的事情。这更像是一个带有指针运算的宏?
这是指类型系统及其处理多维数组的方式吗?谁能解释一下?
最佳答案
是的,这是有道理的,不,它甚至不是在谈论“参差不齐”或“参差不齐”的数组。只是当我们说
int a[NUM_ROWS][NUM_COLS];
我们正在创建的是一个数组 a
,它的数组是……其他数组。你可以这样想:
+---------------------------------------+
| +--------+--------+--------+--------+ |
a: [0]: | | | | | | |
| +--------+--------+--------+--------+ |
+ +
| +--------+--------+--------+--------+ |
[1]: | | | | | | |
| +--------+--------+--------+--------+ |
+ +
| +--------+--------+--------+--------+ |
[2]: | | | | | | |
| +--------+--------+--------+--------+ |
+---------------------------------------+
(这里NUM_COLS
显然是4,NUM_ROWS
是3。)
二维(或更多)维数组与简单的一维数组 100% 相似——您只需要仔细考虑类比即可。如果a
是一个数组,然后任何提及 a
在需要它的值的表达式中会导致指向数组第一个元素的指针,&a[0]
.所以给定二维数组a
我们正在谈论,a
的值为 &a[0]
并且是一个指向 NUM_COLS
数组的指针整数。
如果多维数组下标要正常工作,它必须以这种方式工作。如果我们写 a[i][j]
,这被解释为 (a[i])[j]
. a
像往常一样变成指向数组第一个元素的指针,但是 a[i]
相当于*(a + i)
,其中指针算法最终按指向元素的大小缩放——也就是说,在引擎盖下,它更像是 *(a+ i * sizeof(*a))
.所以sizeof(*a)
必须是 sizeof(int [NUM_COLS])
, 或 NUM_COLS * sizeof(int)
.那样a[i]
给你 i
'th 子数组,然后是 j
可以选择其中一个单元格 -- int
- 大小的单元格 -- 子阵列。
最后一点:我已经通俗地谈论了“多维数组”,但严格来说,正如这里的许多常客喜欢指出的那样,C 没有多维数组;它只有一维数组,而我们认为的二维数组实际上是一维数组,正如我们在这里看到的,其元素恰好是其他一维数组。 (如果 C 有真正的多维数组,下标可能看起来像 a[i,j]
而不是 a[i][j]
。)
附录:尽管你提到了指针算法,我也提到了指针算法,但重要的是要认识到a
中没有涉及指针。的定义。只有当我们试图“获取”a
的值时才会出现指针。 ,或解释如何 a[i]
相当于*(a + i)
.
对于确实涉及指针的数据结构,我们可以对比一下代码描述的情况
int *a2[NUM_ROWS];
for(i = 0; i < NUM_ROWS; i++)
a2[i] = malloc(NUM_COLS * sizeof(int));
这给了我们一个非常不同的内存布局:
+-----+
a2: | | +--------+--------+--------+--------+
| *------->| | | | |
| | +--------+--------+--------+--------+
+-----+
| | +--------+--------+--------+--------+
| *------->| | | | |
| | +--------+--------+--------+--------+
+-----+
| | +--------+--------+--------+--------+
| *------->| | | | |
| | +--------+--------+--------+--------+
+-----+
这就是通常所说的“参差不齐”或“参差不齐”的数组,因为在这种情况下显然没有必要所有行都具有相同的长度。然而,几乎神奇的是,“参差不齐”数组中的单元格也可以使用 a2[i][j]
访问。符号。为了充分发挥活力,我们可以使用
int **a3 = malloc(NUM_ROWS * sizeof(int *));
for(i = 0; i < NUM_ROWS; i++)
a3[i] = malloc(NUM_COLS * sizeof(int));
导致此内存布局:
+-----+
a3: | |
| * |
| | |
+--|--+
|
|
V
+-----+
| | +--------+--------+--------+--------+
| *------->| | | | |
| | +--------+--------+--------+--------+
+-----+
| | +--------+--------+--------+--------+
| *------->| | | | |
| | +--------+--------+--------+--------+
+-----+
| | +--------+--------+--------+--------+
| *------->| | | | |
| | +--------+--------+--------+--------+
+-----+
和a3[i][j]
也在这里工作。
(当然,在构建“动态数组”的实际代码中,如 a2
和 a3
,我们必须检查以确保 malloc
没有返回 NULL
。)
关于C、多维数组: array whose elements are one-dimensional arrays?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51737894/