问题描述
从 C编程:一种现代方法,第二版 在第269页
Does this statement make sense, from the book C Programming: A Modern Approach, 2nd Edition on page 269
int a[NUM_ROWS][NUM_COLS];
a
不是 指向a[0][0];
的指针,而是指向a[0]
的指针. 如果从C的角度来看它,这更有意义,因为C认为a
不是二维数组,而是元素是一维数组的一维数组.用作指针的a
具有类型int (*) [NUM_COLS]
(指向长度为NUM_COLS
的整数数组的指针).
a
is not a pointer to a[0][0];
instead, it's a pointer to a[0]
. This makes more sense if we look at it from the standpoint of C, which regards a
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 type int (*) [NUM_COLS]
(pointer to an integer array of length NUM_COLS
).
我很困惑,因为当我想到其元素是一维数组的数组" 时,我认为锯齿形数组,但这不是这里发生的事情.这更像是带有指针算术的宏?
I'm confused because when I think "array whose elements are one-dimensional arrays" I think a jagged-array, but that's not what's going on here.. This is more like a macro with pointer arithmetic?
这是关于类型系统的参考,以及它如何处理多维数组?有人可以解释吗?
Is this in reference to the type system and how it treats multidimensional arrays? Could any one explain this?
推荐答案
是的,这是有道理的,不是,它甚至不是在谈论参差不齐"或参差不齐"的数组.只是当我们说
Yes, it makes sense, and no, it's not even talking about "ragged" or "jagged" arrays. It's simply that when we say
int a[NUM_ROWS][NUM_COLS];
我们要创建的是一个数组a
,它是一个数组...其他数组.您可以这样想:
what we're creating is an array a
, and what it's an array of is... other arrays. You could think of it like this:
+---------------------------------------+
| +--------+--------+--------+--------+ |
a: [0]: | | | | | | |
| +--------+--------+--------+--------+ |
+ +
| +--------+--------+--------+--------+ |
[1]: | | | | | | |
| +--------+--------+--------+--------+ |
+ +
| +--------+--------+--------+--------+ |
[2]: | | | | | | |
| +--------+--------+--------+--------+ |
+---------------------------------------+
(这里NUM_COLS
显然是4,而NUM_ROWS
是3.)
(Here NUM_COLS
is evidently 4, and NUM_ROWS
is 3.)
二维(或更多)维数组与简单的单维数组100%相似-您只需要仔细考虑这些相似之处即可.如果a
是一个数组,则在需要其值的表达式中对a
的任何提及都会导致指向该数组的第一个元素&a[0]
的指针.因此,考虑到我们正在讨论的二维数组a
,a
的值是&a[0]
,并且是一个指向NUM_COLS
整数的指针.
A two- (or more) dimensional array is 100% analogous to a simple, single-dimensional array -- you just have to be careful thinking about the analogies. If a
is an array, then any mention of a
in an expression where its value is needed results in a pointer to the array's first element, &a[0]
. So given the two-dimensional array a
we're talking about, a
's value is &a[0]
and is a pointer to an array of NUM_COLS
integers.
如果多维数组下标要正常工作,则必须以这种方式工作.如果我们编写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
个子数组,然后j
可以选择该子数组的单元格之一-int
大小的单元格.
It has to work this way, if multidimensional array subscripts are to work correctly. If we write a[i][j]
, that's interpreted as (a[i])[j]
. a
turns into a pointer to the array's first element, as usual, but a[i]
is equivalent to *(a + i)
, where the pointer arithmetic ends up being scaled by the size of the pointed-to element -- that is, under the hood, it's more like *(a+ i * sizeof(*a))
. So sizeof(*a)
has to be sizeof(int [NUM_COLS])
, or NUM_COLS * sizeof(int)
. That way a[i]
gets you the i
'th subarray, and then j
can select one of the cells -- the int
-sized cells -- of the subarray.
最后一点:我曾口头谈论过多维数组",但严格来说,正如这里的许多常客所指出的那样,C没有多维数组.它只有一维数组,正如我们在此处看到的那样,我们实际上认为的二维数组是一维数组,其元素恰好是其他一维数组. (如果C具有真正的多维数组,则下标可能看起来像a[i,j]
而不是a[i][j]
.)
One final note: I've talked colloquially about "multi-dimensional arrays", but strictly speaking, and as many of the regulars here are fond of pointing out, C has no multidimensional arrays; it has only single-dimensional arrays, and what we think of as a two-dimensional array is actually, as we've seen here, a single-dimensional array whose elements happen to be other single-dimensional arrays. (If C had true multi-dimensional arrays, the subscripts would probably look like a[i,j]
instead of a[i][j]
.)
附录:尽管您提到了指针算术,而我也提到了指针算术,但重要的是要认识到 a
的定义中没有涉及指针.仅当我们尝试获取" a
的值或解释a[i]
与*(a + i)
等效时,指针才会出现.
Addendum: Despite your mention of pointer arithmetic, and my mention of pointer arithmetic, it's important to realize that there are no pointers involved in a
's definition. Pointers arise only when we try to "take the value of" a
, or explain how a[i]
is equivalent to *(a + i)
.
对于确实包含指针的数据结构,我们可以对比代码描述的情况
For a data structure that does involve pointers, we could contrast the situation described by the code
int *a2[NUM_ROWS];
for(i = 0; i < NUM_ROWS; i++)
a2[i] = malloc(NUM_COLS * sizeof(int));
这为我们提供了非常不同的内存布局:
This gives us a very different memory layout:
+-----+
a2: | | +--------+--------+--------+--------+
| *------->| | | | |
| | +--------+--------+--------+--------+
+-----+
| | +--------+--------+--------+--------+
| *------->| | | | |
| | +--------+--------+--------+--------+
+-----+
| | +--------+--------+--------+--------+
| *------->| | | | |
| | +--------+--------+--------+--------+
+-----+
这就是通常所说的参差不齐"或参差不齐"的数组,因为在这种情况下,所有行的长度都不必相同.但是,几乎可以神奇地使用a2[i][j]
表示法访问参差不齐"数组中的单元格.为了获得完全的活力,我们可以使用
And this is what's usually called a "ragged" or "jagged" array, since it's obviously not necessary that all the rows in this case be the same length. Nevertheless, almost magically, the cells in the "ragged" array can also be accessed using the a2[i][j]
notation. And for full dynamism, we could use
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
.)
(Of course, in real code constructing "dynamic arrays" like a2
and a3
, we'd have to check to make sure that malloc
didn't return NULL
.)
这篇关于C,多维数组:其元素是一维数组的数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!