8. 二维数组

前面我们学习了一维数组,一维数组是具有相同数据类型的变量排列在一起组成的数据结构。

这一节我们来学习 C 语言中的 二维数组。二维数组你可以看成是多个相同长度的一维数组组成的数组,即:数组的数组。

在软件开发的过程中经常会用到二维数组来表示所需要的数据结构,比如:数学中的矩阵、黑白照片、五子棋或围棋的棋盘等。

在 C 语言中,我们可以认为二维数组使用行和列组成的网格结构。每个网格中的数据元素类型必须一致。

8.1 二维数组声明

二维数组声明的语法:

数据类型 数组名[行整数表达式m][列整数表达式n] = {...}, ...;

语法说明:

  1. 数据类型是数组内所有成员的数据类型,不是数组的数据类型。
  2. 数组名必须是标识符。
  3. 数组名是一个常量,不能使用赋值语句对其进行赋值操作。
  4. 在逻辑上 二维数组 是 m 行 n 列的二维网格的结构,每一行的数据个数都必须相等,每一列的数据个数也必须相等。
  5. 在物理存储时实际是以每一行为单位的 m 个 一维数组依次顺序摆放在内存中。
  6. 行整数表达式m 是整数常量表达式,表示二维数组的行数,在有初始化列表时可以省略不写,由初始化列表推导出行数m。
  7. 列整数表达式n 是整数常量表达式,表示二维数组的列数,此数值必须给出。
  8. = {...} 是数组的初始化列表,此部分可以省略不写,如果不给定初始化列表,数组内的数据元素的值可能是任意值。
  9. 初始化列表 必须是用一对大括号({})括起来的表达式列表,该初始化列表用来初始化数组中每一个数据的初始值。
  10. 二维数组的 初始化列表 的写法是 {{第一行数据的初始化列表},{第二行数据的初始化列表}, ...} 的格式。
  11. 如果 初始化列表 内表达式的个数小于数据元素的个数,则后面其余的数据补充 零值
  12. 行整数表达式m初始化列表 不能同时丢失,否则编译器则因无法确定数组的行数而报错。
  13. , ... 表达式后面还可以声明变量,指针,数组等其它变量。
  14. 数组的每一行有自己的数据类型,每一行的数据类型是 数据类型[列整数表达式n]
  15. 数组有自己的数据类型,数组的数据类型是 数据类型[行整数表达式m][列整数表达式n]

示例:

// filename: 2d_array.c
#include <stdio.h>

int main(int argc, char *argv[]) {
    // 声明 2 行 3 列一共含有 6 个整型数据元素的二维数组。
    int arr2d_1[2][3] = {{1, 2, 3}, {4, 5, 6}};

    // 声明 10 行 20 列的字符型数据的二维数组,内部数据元素都是 '\0'。
    char arr2d_2[10][20] = {};

    // 声明 3 行 4 列的短整型数据的二维数组,内部数据元素是如下结构:
    // 1 2 0 0     //(初始化列表没有给出部分补充 0)
    // 5 6 7 0
    // 0 0 0 0
    short int arr2d_3[][4] = {{1, 2}, {5, 6, 7}, {}};
    // 声明 5 行 2 列整数数据的二维数组,不进行初始化:
    int arr2d_4[5][2];

    printf("sizeof(arr2d_1): %ld\n", sizeof(arr2d_1));
    printf("sizeof(arr2d_2): %ld\n", sizeof(arr2d_2));
    printf("sizeof(arr2d_3): %ld\n", sizeof(arr2d_3));
    printf("sizeof(arr2d_4): %ld\n", sizeof(arr2d_4));
    return 0;
}

运行结果如下:

weimingze@mzstudio:~$ gcc -o 2d_array 2d_array.c
weimingze@mzstudio:~$ ./2d_array
sizeof(arr2d_1): 24
sizeof(arr2d_2): 200
sizeof(arr2d_3): 24
sizeof(arr2d_4): 40

下面我们来看一下 二维数组 int arr2d_1[2][3] = {{1, 2, 3}, {4, 5, 6}}; 的逻辑结构和物理存储结构。

上述二维数组逻辑结构是 2 行 3 列的二维网格如下:

+-----+-----+-----+
|  1  |  2  |  3  |
+-----+-----+-----+
|  4  |  5  |  6  |
+-----+-----+-----+

物理存储结构是 连续的 6 个短整型数据进行存储的一段内存,如下:

----+-----+-----+-----+-----+-----+-----+----
... |  1  |  2  |  3  |  4  |  5  |  6  | ...
----+-----+-----+-----+-----+-----+-----+----