「數組指針、指針數組、函數指針、指針函數」是C語言指針進階學習中的「四大金剛」,也是面試高頻考點。本文通過核心定義、聲明語法、優先級規則、右左法則四個維度,徹底消除概念混淆,建立精確的類型識別能力。
int a[5] = {1,2,3,4,5};
int *p = a; // p 指向首元素
// 1. 下標法:a[i] / p[i]
// 2. 數組名+偏移:*(a+i)
// 3. 指針+偏移:*(p+i)
// 4. 指針下標:p[i] (編譯器自動轉為 *(p+i))
// 結論:數組名在表達式中退化為指向首元素的指針
int a[3] = {2,3,4};
int *p1 = a; // 指向首元素 int*
int (*p2)[3] = &a; // 數組指針:指向 int[3] 類型
// 聲明解析:int (*p)[n]
// () 優先級高 → p 是指針 → 指向 int[n] 類型
// 用途:二維數組行指針、函數參數傳遞整個數組
int a=10, b=20, c=30;
int *pa[3] = {&a, &b, &c}; // 指針數組:int* [3]
// 聲明解析:int *p[n]
// [] 優先級高 → p 是數組 → 元素類型 int*
// 用途:字符串數組、main參數 argv、命令表跳轉
int Max(int a, int b) { return a>b?a:b; }
int (*pfun)(int, int); // 函數指針聲明
pfun = Max; // 函數名即地址,&可省略
pfun = &Max; // 等效
int res = (*pfun)(3,5); // 調用,*可省略
int res = pfun(3,5); // 等效
// 聲明三要素:返回類型、參數類型、參數個數 必須匹配
// 語法:返回類型 (*指針名)(參數列表)
int* GetPtr(int idx) {
static int arr[10];
return &arr[idx]; // 返回地址
}
// 聲明:int *fun(); 等同 int* fun();
// 本質:函數,返回類型為指針
// 用途:工廠函數、鏈表節點創建、動態內存分配封裝
| 聲明 | 結合順序 | 本質 | 關鍵標記 |
|---|---|---|---|
int (*p)[n] | p → *p → (*p)[n] | 指針 | 括號綁定 * |
int *p[n] | p → p[n] → *p[n] | 數組 | [] 綁定 p |
int (*p)(int) | p → *p → (*p)(int) | 指針 | 括號綁定 * |
int *p() | p → p() → *p() | 函數 | () 綁定 p |
步驟:
() 或 [] 時改變方向// 例1:int (*fun)(int *p) fun → 右邊 (int *p) → 函數,參數 int* → 左邊 * → 指針 → 左邊 int → 返回 int 結論:函數指針,指向 參數int* 返回int 的函數 // 例2:int (*fun[5])(int *p) fun → 右邊 [5] → 數組(5個元素) → 左邊 * → 元素是指針 → 跳出 → 右邊 (int *p) → 函數 結論:函數指針數組,5個元素,每個指向 參數int* 返回int 的函數
| 類型 | 聲明示例 | sizeof(類型) | 典型應用 |
|---|---|---|---|
| 數組指針 | int (*p)[10] | 指針大小(4/8字節) | 二維數組形參、矩陣運算 |
| 指針數組 | int *p[10] | 10×指針大小 | 字符串數組、argv、虛函數表 |
| 函數指針 | int (*p)(int,int) | 指針大小 | 回調、狀態機、策略模式 |
| 指針函數 | int* p(int) | 函數代碼大小 | 工廠、分配器、鏈表創建 |
掌握「只看最後兩字識本質、優先級規則辨聲明、右左法則解複雜」三大核心技能,即可輕松應對所有指針類型聲明與識別問題。建議收藏本文對照表,實戰中多寫、多畫內存圖,將語法規則內化為類型直覺。