二維動態數組本質是「行指針數組」,每個元素指向一塊獨立的連續內存(該行數據)。
int **p;
int M = 10, N = 20; // 行、列
int i;
// 1. 分配行指針數組
p = (int **)malloc(sizeof(int *) * M);
if (!p) exit(1);
// 2. 為每行分配數據空間
for (i = 0; i < M; i++) {
p[i] = (int *)malloc(sizeof(int) * N);
if (!p[i]) {
// 分配失敗:釋放已分配的行
for (int j = 0; j < i; j++) free(p[j]);
free(p);
exit(1);
}
}
// 3. 使用:p[row][col] 訪問
p[3][5] = 100;
// 4. 釋放:先釋放每行,再釋放行指針數組
for (i = 0; i < M; i++) free(p[i]);
free(p);
p = NULL; // 防野指針
優點:內存連續、緩存友好、釋放只需一次 free。
// 分配
int *data = (int *)malloc(sizeof(int) * M * N);
int **p = (int **)malloc(sizeof(int *) * M);
for (i = 0; i < M; i++) p[i] = data + i * N;
// 使用同樣 p[i][j]
// 釋放
free(data);
free(p);
free(p) 再釋放行 → 內存洩漏(行指針丟失)。int *[M] 與 int **:前者是定長數組(棧上),後者是動態指針(堆上)。| 方案 | 優點 | 缺點 | 適用 |
|---|---|---|---|
| 雙重指針 | 每行長度可不同、擴容靈活 | 內存不連續、多次 malloc 慢、釋放繁瑣 | 不規則矩陣、頻繁增減行 |
| 連續塊 | 高效、緩存友好、簡單釋放 | 行長固定、擴容需整體遷移 | 矩陣運算、圖像處理、高性能計算 |