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

时间:2018-08-08 02:42:33

标签: c arrays pointers multidimensional-array

从第269页的C Programming: A Modern Approach, 2nd Edition这本书开始,这ç§è¯´æ³•æœ‰æ„义å—

  

å°±åƒä¸€ç»´æ•°ç»„çš„å称å¯ä»¥ç”¨ä½œæŒ‡é’ˆä¸€æ ·ï¼Œ any 数组的å称也å¯ä»¥ç”¨ä½œæŒ‡é’ˆï¼Œè€Œä¸ç®¡å®ƒæœ‰å¤šå°‘维。但是,需è¦å°å¿ƒã€‚考虑以下数组:

source ./Scripts/activate
     

int a[NUM_ROWS][NUM_COLS]; ä¸æ˜¯æŒ‡å‘a的指针,而是指å‘a[0][0];的指针。 如果从C的角度æ¥çœ‹å®ƒï¼Œè¿™å°†æ›´æœ‰æ„义,因为Cå°†a[0]视为ä¸æ˜¯äºŒç»´æ•°ç»„,而是将其视为一维数组的一维数组。当用作指针时,a的类型为a(指å‘长度为int (*) [NUM_COLS]的整数数组的指针)。

我很困惑,因为当我想到“其元素是一维数组的数组†时,我认为是jagged-array,但这ä¸æ˜¯è¿™é‡Œè¦å‘生的事情。有指针算术的å®ï¼Ÿ

这是关于类型系统的å‚考,以åŠå®ƒå¦‚何处ç†å¤šç»´æ•°ç»„?有人å¯ä»¥è§£é‡Šå—?

2 个答案:

答案 0 :(得分:7)

是的,这是有é“ç†çš„,ä¸æ˜¯ï¼Œå®ƒç”šè‡³ä¸æ˜¯åœ¨è°ˆè®ºâ€œå‚å·®ä¸é½â€æˆ–“å‚å·®ä¸é½â€çš„数组。åªæ˜¯å½“我们说

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整数数组的指针< / em>。

如果多维数组下标è¦æ­£å¸¸å·¥ä½œï¼Œåˆ™å¿…须以这ç§æ–¹å¼å·¥ä½œã€‚如果我们写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)。 / p>

最åŽä¸€ç‚¹ï¼šæˆ‘曾å£å¤´è°ˆè®ºè¿‡â€œå¤šç»´æ•°ç»„â€ï¼Œä½†ä¸¥æ ¼æ¥è¯´ï¼Œæ­£å¦‚这里的许多常客所指出的那样,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ä¸ä¼šè¿”回{{1 }}。

答案 1 :(得分:3)

å¦ä¸€ç§æŸ¥çœ‹æ–¹å¼...

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

T arr[N];

其中Tå¯ä»¥æ˜¯int,char,double,struct foo,无论是什么,都读为“ {{1}çš„N元素数组}â€ã€‚也å¯ä»¥æ˜¯å¦ä¸€ç§æ•°ç»„类型。因此,å‡è®¾Tä¸ä»…仅是intçš„ M元素数组,我们将其写为

T

这表示为“ int是int arr[N][M]; çš„M元素数组的N元素数组â€ã€‚è¿™ä¸æ˜¯é”¯é½¿çŠ¶çš„阵列-所有“行â€çš„大å°å‡ç›¸åŒã€‚但这也ä¸å®Œå…¨æ˜¯äºŒç»´æ•°ç»„-它是数组的数组。表达å¼arr具有数组类型(int)。

此视图还帮助我们找出指å‘数组类型的指针。除éžå®ƒæ˜¯arr[i]或一元int [M]è¿ç®—符的æ“作数,或者是用于在声明中åˆå§‹åŒ–字符数组的字符串文字,å¦åˆ™ç±»åž‹ä¸ºâ€œ Nâ€çš„ expression sizeofâ€ï¼ˆ&)的-element数组将被转æ¢ï¼ˆâ€œè¡°å‡â€ï¼‰ä¸ºâ€œæŒ‡å‘T的指针(T [N])类型的表达å¼ã€‚åŒæ ·ï¼Œå¦‚果将T替æ¢ä¸ºæ•°ç»„类型T *,则表达å¼ä¸ºâ€œ Tçš„M元素数组的N元素数组â€ï¼ˆint [M] ),它会“衰å‡â€ä»¥é”®å…¥â€œ intçš„M元素数组的指针â€ï¼ˆint [N][M])。