C/C++ 聲明遵循 聲明模仿使用 原則:聲明符 的形式模仿表達式求值形式。解讀遵循 右左法則 (Clockwise/Spiral Rule):
() 函數, [] 數組)。* 指針, const, volatile)。() 重複 2-3 步驟。const int *p
p // 標識符
* // 左:指針 → p 是指針
const int // 左:基礎類型 const int
→ p 是指向 const int 的指針 (底層 const)
int * const p
p
* const // 左:const 修飾 * → p 是常量指針
int // 左:基礎類型 int
→ p 是指向 int 的常量指針 (頂層 const)
int (*p)[10]
p
(*p) // 右:() 優先 → p 是指針
(*p)[10] // 右:[] → 指向大小 10 的數組
int // 左:基礎類型
→ p 是指向含 10 個 int 的數組的指針
int *p[10]
p
p[10] // 右:[] 結合緊密 → p 是大小 10 的數組
*p[10] // 左:* → 數組元素是指針
int // 左:基礎類型
→ p 是含 10 個指向 int 指針的數組
int (*fp)(double, char)
fp
(*fp) // 右:() → fp 是指針
(*fp)(double, char) // 右:() 參數列表 → 指向函數
int // 左:返回類型
→ fp 是指向「接受 double, char 返回 int 的函數」的指針
int (*fp[5])(double)
fp
fp[5] // 右:[] → fp 是大小 5 的數組
(*fp[5]) // 左:* → 數組元素是指針
(*fp[5])(double) // 右:() → 指向函數
int // 左:返回類型
→ fp 是含 5 個「指向接受 double 返回 int 的函數指針」的數組
// 函數指針類型
typedef int (*FuncPtr)(double, char);
FuncPtr fp1, fp2; // 清晰易讀
// 函數指針數組
typedef int (*FuncPtrArr[5])(double);
FuncPtrArr table;
// 遞歸結構體
typedef struct Node {
int val;
struct Node* next;
} Node;
Node* head;
// C++11 別名模板 (更強大)
template
using FuncPtrT = int (*)(T, char);
FuncPtrT fp3;
| 聲明 | 含義 | 修飾層級 |
|---|---|---|
const int *p / int const *p | 指向 const int 的指針 | 底層 const (指向的對象不可修改) |
int * const p | 指向 int 的常量指針 | 頂層 const (指針本身不可修改) |
const int * const p | 指向 const int 的常量指針 | 雙重 const |
volatile int *p | 指向 volatile int 的指針 | 底層 volatile (硬件/信號可變) |
int * volatile p | 指向 int 的 volatile 指針 | 頂層 volatile (指針值可能意外變化) |
判斷口訣:* 右側的 const/volatile 修飾指針本身 (頂層),左側修飾指向對象 (底層)。
std::function<R(Args...)>、Lambda、std::invoke。std::vector<std::function<...>>、std::array。auto fp = [](double d, char c) -> int { ... }; 編譯器自動推導類型。template F> 替代函數指針參數。
// GCC/Clang
gcc -c -fdump-lang-all test.c // 生成 .tu 文件含類型樹
// 或使用神器 cdecl (命令行工具)
$ cdecl> explain int (*(*fp[5])())(double)
declare fp as array 5 of pointer to function returning pointer to function returning int
在線工具:cdecl.org — 輸入聲明獲取英文解釋,輸入英文獲取聲明。