C 語言宣告語法以「右左規則」(順時針螺旋法)聞名遺憾,導致許多易混淆概念成為面試高頻考點與 Bug 溫床。本文系統梳理四大核心辨析,配合記憶口訣與實戰範例,助你徹底搞懂。
| 概念 | 宣告 | 含義 | 記憶口訣 |
|---|---|---|---|
| 指標陣列 | int *p[10]; | 陣列,元素型別為 int*,共 10 個指標 | 「陣列」是主語 → 先看 [10] |
| 陣列指標 | int (*p)[10]; | 指標,指向型別為 int[10] 的陣列 | 「指標」是主語 → 先看 *p |
int *ptr_arr[3]; // 3 個 int 指標
int (*arr_ptr)[3]; // 1 個指向 3 元素 int 陣列的指標
int a[3] = {1,2,3};
arr_ptr = &a; // 正確
// ptr_arr = &a; // 錯誤:型別不匹配
// 遍歷二維陣列時常用陣列指標
int matrix[2][3] = {{1,2,3},{4,5,6}};
int (*p)[3] = matrix; // matrix 退化為指向首行的指標
for (int i=0; i<2; i++) {
for (int j=0; j<3; j++) printf("%d ", p[i][j]);
}
| 概念 | 宣告 | 含義 | 記憶口訣 |
|---|---|---|---|
| 函數指標 | int (*p)(int, int); | 指標,指向「參數兩 int、回傳 int」的函數 | 「指標」是主語 → *p 是函數 |
| 指標函數 | int *p(int, int); | 函數,參數兩 int、回傳 int* | 「函數」是主語 → 回傳指標 |
int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }
int (*op)(int, int) = add;
printf("%d\n", op(3, 5)); // 8
op = sub;
printf("%d\n", op(3, 5)); // -2
// 配合 typedef 簡化
typedef int (*BinaryOp)(int, int);
BinaryOp ops[] = {add, sub, NULL};
| 寫法 | 型別 | 儲存區 | 可修改性 | 典型錯誤 |
|---|---|---|---|---|
char *p = "hello"; | char* | 唯讀資料段 | **不可修改** → UB | p[0] = 'H'; Crash |
char a[] = "hello"; | char[6] | 堆疊(區域) | **可修改** | a[0] = 'H'; OK |
「指標指向常量區,陣列複製到堆疊。」
核心口訣:const 修飾誰,誰就不可變。
| 宣告 | 別名 | const 修飾對象 | 限制 | 允許 |
|---|---|---|---|---|
const int *p;int const *p; | 常量指標 (Pointer to Const) | *p (指向的值) | *p = 10; ❌p = &x; ✅ | 修改指標指向 |
int *const p; | 指標常量 (Const Pointer) | p (指標本身) | p = &x; ❌*p = 10; ✅ | 修改指向的值 |
const int *const p; | 常量指標常量 | 雙重修飾 | 雙重限制 | 僅初始化 |
int a = 10, b = 20;
const int *p1 = &a; // p1 可變,*p1 不可變
p1 = &b; // OK
// *p1 = 30; // Error
int *const p2 = &a; // p2 不可變,*p2 可變
*p2 = 30; // OK, a 變為 30
// p2 = &b; // Error
// 函數參數傳遞:防止誤修改
void print_str(const char *str); // 承諾不修改 str 指向的內容
宣告:const int *(*p[5])(int, const char*);
p 是陣列 [5] → 指標陣列。const int *(*)(int, const char*) → 函數指標。int, const char*,回傳 const int*。p 是含 5 個函數指標的陣列,每個指向「接受 int 和常量字串、回傳常量整數指標」的函數。[] 還是 * 先結合變數名。const 在 * 左邊修飾值,右邊修飾指標。typedef int (*FunPtr)(int);。cdecl 工具或 IDE 懸停提示可驗證理解。徹底掌握這四組辨析,C 語言宣告將不再是閱讀障礙,而是精準表達意圖的利器。