C、多维数组: array whose elements are one-dimensional arrays?

标签 c arrays pointers multidimensional-array

这个说法有道理吗,出自书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 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).

我很困惑,因为当我想到“其元素是一维数组的数组”时,我想到了一个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]也在这里工作。

(当然,在构建“动态数组”的实际代码中,如 a2a3 ,我们必须检查以确保 malloc 没有返回 NULL。)

关于C、多维数组: array whose elements are one-dimensional arrays?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51737894/

相关文章:

c++ - 如何在指针初始化为数组的第一个索引后释放指针?

c - 如果字符指针指向的只读存储器不是连续的,那么它们如何工作?

c - 如何在 C 中实现复杂的算术运算符?

C 代码未按预期运行

c++ - 无法理解 C 和 C++ 中缓冲区大小的不同实验结果。 ifstream 也比 FILE 慢吗?

c++ - 删除动态数组时会发生什么?

具有多个指针和括号的 C 语法

java - 在 Java 中为链中的变量赋值

javascript - 在 Javascript 中有效组合多个数组方法转换

c# - 在 C# struct pointer 中返回相同的地址