二维(多维)数组


一维数组使用数组名称与一个索引值来指定访问数组元素,二维数组使用数组名称与两个索引值来指定访问数组元素,定义方式与一维数组类似:

int maze[5][10];

上面这个定义会配置 5 * 10 = 50 个整数的内存空间给数组来使用,二维数组使用两个索引值来指定访问数组,这两个索引值都是由 0 开始,下面这个程序简单的示范二维数组的访问:

#include <stdio.h>
#define ROW 5
#define COLUMN 10

int main(void) {
    int maze[ROW][COLUMN];

    for(int i = 0; i < ROW; i++) {
        for(int j = 0; j < COLUMN; j++) {
            maze[i][j] = (i + 1) * (j + 1);
        }
    }

    for(int i = 0; i < ROW; i++) {
        for(int j = 0; j < COLUMN; j++) {
            printf("%d\t", maze[i][j]);
        }
        putchar('\n');
    }

    return 0;
}

执行结果:

1       2       3       4       5       6       7       8       9       10      
2       4       6       8       10      12      14      16      18      20      
3       6       9       12      15      18      21      24      27      30
4       8       12      16      20      24      28      32      36      40
5       10      15      20      25      30      35      40      45      50

在上面这个程序中,定义了 5 列(Row)、10 行(Column)的数组,第一个[]是用来指定访问哪一列,第二个[]是用来指定访问哪一行,所以使用maze[i][j]时,表示要访问ij行的元素。

也可以在定义二维数组的同时指定二维数组的值,例如:

int maze[2][3] = {
                     {1, 2, 3},
                     {4, 5, 6}
                 };

从上面这个程序来看,可以清楚地看出maze[2][3]中 2 与 3 的意义,maze[2]表示maze有两个元素,各是{1, 2, 3}{4, 5, 6},也就是说,这两个元素是一维数组,而长度是 3。

若清楚二维数组的内存配置方式,会理解到{}其实是可以不用的,例如:

int maze[2][3] = {
                     1, 2, 3,
                     4, 5, 6
                 };

何谓二维数组于内存中的配置方式?其实数组访问时的行与列,是为了理解数组元素的指定访问而想像出来的,索引值正确的意义,是指相对于数组第一个元素 的位移量,例如在一维数组中的数组配置与索引意义如下图所示:

二维(多维)数组

int整数数组来说,每一位移量是 4 个字节,而指定访问maze[4],相当于指定访问相对于maze[0]四个位移量的内存空间。

即使是二维空间,其在内存中也是线性配置的,例如:

二维(多维)数组

在上面的例子中,二维数组将得到的内存分为两个区块,我们定义数组maze[2[4],表示maze[0][0]maze[1][0]相对位移量为 4,当指定访问maze[1][3]时,表示访问的位置是相对于maze[1][0]位移 3 个单位。

若定义maze[3][5]的话,内存位置的指定是如何呢?在这个数组中 5 的意义是maze[0][0]maze[1][0]maze[2][0]的位置各相对 5 个位移量,如下图所示:

二维(多维)数组

了解二维数组在内存中的配置关系后,就可以知道,上图可以看成是三个一维数组在内存中连续配置,严格来说,C 没有二维数组这种东西,二维或多维数组的概念,是以数组的数组(arrays of arrays)来实现。

可以使用底下的程序来验证所谓的二维数组,就是具有两个一维数组作为元素的数组:

#include <stdio.h>
#define ROWS 2
#define LEN 3

int main(void) {
    int maze[ROWS][LEN] = {
                              {1, 2, 3},
                              {4, 5, 6}
                          };

    for(int i = 0; i < ROWS; i++) {
        int *row = maze[i];
        for(int j = 0; j < LEN; j++) {
            printf("%d\t", row[j]); 
        }
        printf("\n");
    } 
}

就目前来说,可以知道的是maze[i]为每个一维int数组的地址,类型是int*,这是指针类型,之后会谈到,也就是说row代表了每个一维int数组,因而内层for循环可以使用索引来获取一维数组内容。

更多维的数组,就是依以上说明类推罢了,例如三维数组:

int arr[2][4][6];




展开阅读全文