首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

函式指標與回呼機制:從宣告到呼叫慣例的完整指南

     編輯:關於C++

為什麼需要函式指標?

回呼函式無法由程式設計師直接呼叫,必須將其位址傳遞給呼叫端。函式指標正是實現此機制的關鍵——它儲存函式的進入點位址,允許執行期動態綁定。

一、函式指標宣告語法解析

一般函式宣告:void f();
對應函式指標型別:void (*)();

  • 括號內的 * 標識「指標」。
  • 左側 void 為回傳型別,右側 () 為參數列。
  • 此為型別,非變數。可用於 sizeof 或 typedef。
// 取得函式指標大小
unsigned psize = sizeof(void (*)());

// 定義型別別名
typedef void (*pfv)();  // pfv:指向無參、回傳 void 的函式指標

// 宣告指標變數
void (*p)();  // p 為指標變數名

二、指標賦值與呼叫

void func() { /* ... */ }

p = func;        // 賦值:函式名即位址
p();             // 透過指標呼叫
(*p)();          // 等價寫法

賦值的函式必須簽章完全相符(回傳型別、參數型別、順序、呼叫慣例)。

三、實現回呼:傳遞指標給呼叫端

void caller(void (*ptr)()) {  // 接受函式指標參數
    ptr();                     // 呼叫被指向的函式
}

int main() {
    p = func;
    caller(p);                 // 動態綁定:執行期決定呼叫哪個函式
}

若 p 在執行期賦予不同函式位址,caller 將呼叫不同函式,實現多型行為。

四、呼叫慣例:隱藏的型別相容性關鍵

呼叫慣例決定:參數壓棧順序(左→右/右→左)、堆疊清理責任(呼叫端/被呼叫端)、參數傳遞機制(堆疊/暫存器)、名稱修飾。常見慣例:

  • __cdecl(C/C++ 預設,呼叫端清理堆疊,支援可變參數)
  • __stdcall(Win32 API 標準,被呼叫端清理堆疊)
  • __fastcall(優先用暫存器傳參)
  • __pascal(左→右壓棧,被呼叫端清理)

慣例不相容導致編譯錯誤


__stdcall int callee(int);              // 被呼叫端用 stdcall
void caller(__cdecl int (*ptr)(int));   // 呼叫端期望 cdecl 指標

__cdecl int (*p)(int) = callee;         // 錯誤:型別不相容!
// 雖然回傳/參數皆為 int,但呼叫慣例不同,屬不同型別

鐵律:呼叫慣例是函式型別的一部分。指標型別與目標函式的慣例必須嚴格一致,否則無法賦值。

五、類別成員函式指標:另一個世界

本文僅涵蓋普通函式指標。類別成員函式指標語法、語義、大小皆不同(涉及 this 指標調整、虛函式表查找等),將另文探討。

總結

  1. 函式指標宣告核心:回傳型別 (*指標名)(參數列),善用 typedef 簡化。
  2. 賦值需簽章與呼叫慣例雙重匹配。
  3. 回呼模式實現執行期動態綁定,廣泛用於事件驅動、排序比較、非同步通知等場景。
  4. 跨模組/動態連結庫傳遞函式指標時,務必統一呼叫慣例(通常約定 __stdcall 或 __cdecl)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved