void fun() { printf("fun"); }
void (*fp)() = fun;
fp(); *fp(); **fp(); ***fp(); // 全部正常輸出 "fun"
普通指標 int *p 若 **p 會報錯,函數指標卻可任意加 *。
fun、&fun、*fun、**fun 在表達式中**自動轉換為函數指標值**(地址)。*fp 的型別是「函數型別」,在調用語境下再次隱式轉換為指標。遞歸解引用不改變本質值。() 接受函數指標或函數型別(隱式轉換)。The expression that denotes the called function shall have type pointer to function returning void or returning a complete object type other than an array type.
函數指標、解引用後的函數指標、函數名、&函數名 皆滿足此型別要求。
int a = 10, *p = &a, **pp = &p;
printf("%d", *p); // 10
printf("%d", **pp); // 10
printf("%d", ***ppp); // 錯誤:***ppp 型別為 int,非指標,不可再解引用
物件指標每解引用一次層級遞減,最終得到物件值,不可再解引用。
fp()**,最清晰。fp = fun 或 fp = &fun 均可,推薦前者(與函數名用法一致)。(**fp)() 等寫法,但新代碼請勿濫用。函數指標「解引用不變層級」是 C 語言為了統一函數調用語法特意設計的規則。