當陣列下標超過 1 個時,即為多維陣列。本質上是「陣列的陣列」:二維陣列是多個一維陣列的集合,三維陣列是多個二維陣列的集合,以此類推。
// 二維陣列:3 列 4 行 int matrix[3][4]; // 三維陣列:2 層 3 列 4 行 int cube[2][3][4];
C 語言採用 Row-Major,最後一個下標變化最快,記憶體連續分布:
int a[2][3] = {{1,2,3}, {4,5,6}};
// 記憶體實際順序:1,2,3,4,5,6
// a[0][0], a[0][1], a[0][2], a[1][0], a[1][1], a[1][2]
總大小 = 維度乘積 × 元素大小。sizeof(a) 回傳整個陣列佔用位元組數。
// 完整初始化
int a[2][3] = {{1,2,3}, {4,5,6}};
// 部分初始化,其餘自動補 0
int b[2][3] = {{1}, {4}}; // 等同 {{1,0,0}, {4,0,0}}
// 省略第一維,由編譯器推導
int c[][3] = {{1,2,3}, {4,5,6}}; // 推導為 2x3
// 動態分配二維陣列(連續記憶體)
int (*p)[3] = malloc(2 * sizeof(*p)); // 指向 int[3] 的指標
p[0][0] = 1; // 正常使用 p[i][j]
// 二維
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
process(a[i][j]);
// 三維
for (int i = 0; i < depth; i++)
for (int j = 0; j < rows; j++)
for (int k = 0; k < cols; k++)
process(cube[i][j][k]);
// 二維陣列 a[rows][cols]
int *ptr = &a[0][0];
for (int i = 0; i < rows * cols; i++)
process(ptr[i]); // 連續掃描,Cache 友善
| 方式 | 原型 | 呼叫 | 適用場景 |
|---|---|---|---|
| 固定第二維 | void foo(int a[][COLS], int rows) | foo(arr, ROWS) | 編譯期已知列數 |
| 指標到陣列 | void foo(int (*a)[COLS], int rows) | foo(arr, ROWS) | 同上,語意更清晰 |
| 扁平化一維 | void foo(int *a, int rows, int cols) | foo(&arr[0][0], ROWS, COLS) | 動態維度、跨函數通用 |
a[2][3] 存取 a[2][3] 會導致未定義行為。int a[][] 不合法,必須指定除第一維外的所有維度大小。int (*p)[cols] = malloc(rows * sizeof(*p)),存取快、釋放簡單。int **p = malloc(rows * sizeof(int*)),每行再 malloc,行長可變但記憶體不連續、釋放繁瑣。a[i][j] 中 j 為內層),符合記憶體連續分布,大幅降低 Cache Miss。void transpose(int src[][4], int dst[][3], int rows, int cols) {
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
dst[j][i] = src[i][j];
}