| 聲明 | 實際類型 | 能否直接 a[i][j] 訪問 | 適用場景 |
|---|---|---|---|
void func(int **a, int m, int n) | int** 指向指針的指針 | ❌ 編譯錯誤/運行時崩潰 | 動態分配的不規則二維數組(指針數組) |
void func(int *a[], int m, int n) | int** 同左,語法糖 | ❌ 同上 | 同上 |
void func(int a[][10], int m, int n) | int (*)[10] 指向 10 元素 int 數組的指針 | ✅ 編譯器知曉列跨度,正常訪問 | 靜態/棧上定義的固定列數二維數組 |
二維數組在內存中是**連續存儲**的。訪問 a[i][j] 實際計算偏移:
address = base_address + (i * COLS + j) * sizeof(int)
int a[][10] 告訴編譯器 COLS = 10,偏移計算確定int **a 僅知道「指向指針」,不知每行長度,無法計算偏移#include <iostream>
using namespace std;
// ✅ 正確:固定列數 10
void func_ok(int a[][10], int m, int n) {
cout << a[m][n] << endl; // 輸出 6 (對應 a[1][5])
}
// ❌ 錯誤:int** 版本
// void func_err(int **a, int m, int n) { cout << a[m][n] << endl; } // 編譯報錯
int main() {
int a[2][10];
for (int i = 0; i < 2; i++)
for (int j = 0; j < 10; j++)
a[i][j] = i + j; // a[1][5] = 6
func_ok(a, 1, 5);
return 0;
}
若列數不固定或堆上分配,推薦「扁平化一維數組 + 手動計算索引」:
void func_flat(int *a, int rows, int cols, int m, int n) {
cout << a[m * cols + n] << endl; // 手動展開
}
// 調用
vector<int> flat(rows * cols);
func_flat(flat.data(), rows, cols, 1, 5);
或使用 std::vector<std::vector<int>> / std::span (C++20) 等現代容器避開裸指針陷阱。
「形參寫死列數,實參傳首地址;動態扁平手算索引,現代容器更安心。」