首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

C 語言函數指標解引用特性:為何 *、*** 均可調用不報錯?

     編輯:程式設計疑難解答

現象

void fun() { printf("fun"); }
void (*fp)() = fun;
fp(); *fp(); **fp(); ***fp(); // 全部正常輸出 "fun"

普通指標 int *p 若 **p 會報錯,函數指標卻可任意加 *。

核心原因

  1. 函數名本身就是函數指標常量:fun、&fun、*fun、**fun 在表達式中**自動轉換為函數指標值**(地址)。
  2. 函數指標解引用仍得函數指標:*fp 的型別是「函數型別」,在調用語境下再次隱式轉換為指標。遞歸解引用不改變本質值。
  3. C 標準規定:函數指標的解引用操作結果仍為函數指標,調用運算子 () 接受函數指標或函數型別(隱式轉換)。

標準引用 (C99 6.5.2.2/1)

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 語言為了統一函數調用語法特意設計的規則。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved