二維陣列是矩陣運算、影像處理、棋盤遊戲的基礎資料結構。本文完整解析 C 語言二維陣列的Row-major 記憶體佈局、指標等價關係、動態配置三種模式、函式參數傳遞,並以「分科成績統計」實戰範例串聯核心觀念。
int matrix[3][4] = {
{0, 1, 2, 3},
{4, 5, 6, 7},
{8, 9, 10, 11}
};
// 等價於 int matrix[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};(按列序)
int m[][4] = {...};邏輯上 3×4 矩陣,物理上為 12 個 int 連續排列:
位址: 1000 1004 1008 1012 | 1016 1020 1024 1028 | 1032 1036 1040 1044
值: 0 1 2 3 | 4 5 6 7 | 8 9 10 11
←──── 列 0 ────→ ←──── 列 1 ────→ ←──── 列 2 ────→
a[i][j] 位址公式:base + (i * COLS + j) * sizeof(int)
| 表示式 | 型別 | 值/含義 |
|---|---|---|
a | int (*)[4] | 陣列位址 = 第 0 列位址 |
a[0], *a, &a[0][0] | int* | 第 0 列首元素位址 |
a+1, &a[1] | int (*)[4] | 第 1 列位址(+16 bytes) |
a[i], *(a+i), &a[i][0] | int* | 第 i 列首元素位址 |
a[i]+j, *(a+i)+j, &a[i][j] | int* | 第 i 列第 j 元素位址 |
*(*(a+i)+j), a[i][j] | int | 元素值 |
| 模式 | 程式碼 | 記憶體特性 | 適用場景 |
|---|---|---|---|
| 單一連續區塊 | int *p = malloc(r*c*sizeof(int)); | 完全連續,p[i*c+j] 存取 | 高效能、需傳給 qsort/BLAS |
| 指標陣列(列指標) | int **p = malloc(r*sizeof(int*)); for(i) p[i]=malloc(c*sizeof(int)); | 各列獨立,不連續 | 列長度不一、頻繁增刪列 |
| 指向陣列的指標 | int (*p)[C] = malloc(r*sizeof(int[C])); | 完全連續,保留 p[i][j] 語法 | 編譯期知行數 C、需二維語法 |
int *mat = malloc(rows * cols * sizeof(int));
mat[i*cols + j] = val; // 手動計算索引
// 釋放:free(mat);
// 固定行數 COLS
int (*mat)[COLS] = malloc(rows * sizeof(int[COLS]));
mat[i][j] = val; // 自然語法
// 釋放:free(mat);
#include
#define STUDENTS 5
#define SUBJECTS 3
int main() {
int score[STUDENTS][SUBJECTS];
float avg[SUBJECTS] = {0};
int i, j;
printf("輸入 %d 位學生 %d 科成績:\n", STUDENTS, SUBJECTS);
for (j = 0; j < SUBJECTS; ++j) {
for (i = 0; i < STUDENTS; ++i) {
scanf("%d", &score[i][j]);
avg[j] += score[i][j];
}
avg[j] /= STUDENTS;
}
printf("\n科目平均: ");
for (j = 0; j < SUBJECTS; ++j) printf("%.1f ", avg[j]);
float total = 0;
for (j = 0; j < SUBJECTS; ++j) total += avg[j];
printf("\n全科總平均: %.1f\n", total / SUBJECTS);
return 0;
}
// 正確:指定行數
void print(int a[][4], int rows);
void print(int (*a)[4], int rows); // 等價
// 錯誤:int a[][]、int **a(除非動態配置模式二)
呼叫時直接傳陣列名:print(mat, 3); → mat 退化為 int(*)[4]。
void transpose(int n, int a[][n]) { // C99 VLA
for (int i=0; i
C = A × B
void matmul(int r1, int c1, int c2,
int A[][c1], int B[][c2], int C[][c2]) {
for (int i=0; i
int a[][] 參數宣告 → 編譯錯誤(行數未知)。int **p = a; 型別不匹配(靜態二維陣列非指標陣列)。free → 記憶體洩漏。malloc)。i-k-j 可提升快取命中率(c1 較大時)。掌握 Row-major 佈局與三種動態配置模式,二維陣列操作將不再有隱藏驚悚。