繁体   English   中英

C,多维数组:元素是一维数组的数组?

[英]C, Multidimensional arrays: array whose elements are one-dimensional arrays?

C编程:现代方法,第269页第2版一书中可以看出这一陈述是否有意义

就像一维数组的名称可以用作指针一样, 任何数组的名称都可以使用,无论它具有多少维度。 但是,需要注意一些事项。 考虑以下数组:

 int a[NUM_ROWS][NUM_COLS]; 

a 不是指向a[0][0];的指针a[0][0]; 相反,它是指向a[0]的指针。 这使得如果我们看它从C,其视性的观点出发更感a不作为二维阵列,但作为一维数组,其元素是一维阵列。 当用作指针时, a具有类型int (*) [NUM_COLS] (指向长度为NUM_COLS的整数数组的NUM_COLS )。

我很困惑,因为当我认为“其元素是一维数组的数组”时,我认为是一个锯齿状数组 ,但这不是这里发生的事情。这更像是一个带指针算术的宏?

这是参考类型系统以及它如何处理多维数组? 任何人都能解释一下吗?

是的,它是有道理的,不,它甚至没有谈论“衣衫褴褛”或“锯齿状”阵列。 就在我们说的时候

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 “个子阵,然后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 。)

另一种看待它的方式......

对于任何类型T ,我们创建一个数组作为

T arr[N];

其中T可以是intchardoublestruct foo ,等等,并读作“ T N元素数组”。 它也可以是另一种数组类型 所以,而不只是int ,假设T是的M-元素的数组 int ,我们会为写

int arr[N][M];

这读作“ arrint元素的M元素数组的N元素数组”。 这不是一个锯齿状的数组 - 所有“行”都是相同的大小。 但它也不完全是一个二维数组 - 它是一个数组数组。 表达式arr[i]具有数组类型( int [M] )。

这个视图也帮助我们找出指向数组类型的指针。 除非它是sizeof或一元&运算符的操作数,或者是用于初始化声明中的字符数组的字符串文字,否则将转换类型为“N元素数组T ”( T [N] )的表达式 (“衰变”)到“指向T指针”( T * )类型的表达式。 同样,如果用数组类型int [M]替换T ,那么你有一个类型为“N元素数组的M元素数组int ”( int [N][M] )的表达式,它“衰变”为输入“指针的M-元件阵列int ”( int (*)[M]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM