曾被 int * (* (*fp1) (int) ) [10]; 這類宣告搞暈?本文從基礎出發,循序漸進教你掌握「右左法則」,輕鬆解讀任何複雜宣告。注意:複雜宣告非良好程式風格,本文僅教導理解技巧。
int n; // n 是 int
int *p; // p 是 int* (指向 int 的指標)
char **argv; // argv 是 char** (指標的指標)
建議寫法:int *p; 而非 int* p;,避免 int* p, q; 誤以為 q 也是指標(實為 int)。
int RollNum[30][4];
int (*p)[4] = RollNum; // p 是指向「4 個 int 的陣列」的指標
int *q[5]; // q 是「5 個 int* 的陣列」
記住:[] 優先級高於 *,int *q[5] 解讀為 int *(q[5])。
int **p1; // int 的指標的指標
int *&p2; // int* 的參考
int &*p3; // 錯誤:參考的指標非法
int &&p4; // 錯誤:參考的參考非法(C++11 右值參考除外)
)。(。int * (* (*fp1) (int) ) [10];fp1 開始。) 停止。* → 「是一個指標」。(int) → 「指向接受 int 參數的函式」。* → 「的指標」。[10] → 「回傳 10 元素陣列」。* → 「的指標」。int。結果:fp1 是一個指標,指向一個接受 int 參數的函式,該函式回傳一個指標,指向一個包含 10 個 int 指標的陣列。
void (*signal(int, void (*fp)(int)))(int);經典 signal 函式宣告。依右左法則解讀:signal 是函式,接受 int 和函式指標,回傳函式指標(接受 int,回傳 void)。
typedef int (*FuncPtr)(int); // 函式指標型別
typedef int (*(*FuncPtrPtr)(int))[10]; // 更複雜的型別
FuncPtrPtr fp1; // 瞬間清爽
善用 typedef 或 C++11 using 別名,將複雜宣告封裝為可讀型別名稱,是工程實務最佳做法。
const int *p / int const *p:指向常數整數的指標(資料不可改)。int * const p:常數指標(指標本身不可改,指向的資料可改)。const int * const p:常數指標指向常數整數。口訣:* 左邊的 const 修飾資料,右邊修飾指標。
掌握右左法則,配合 typedef,任何宣告都能精準解讀。但實際專案中,請盡量避免過度複雜的宣告,改用型別別名提升可維護性。