函數指針存儲函數在代碼段的入口地址,聲明語法:
返回類型 (*指針變量名)(參數列表);
例:int (*pf)(int, int); — 指向「接受兩個 int、返回 int」的函數。
int Sum(int a, int b) { return a + b; }
int Sub(int a, int b) { return a - b; }
int main() {
int (*pf)(int, int); // 聲明
pf = Sum; // 賦值(函數名隱式轉換為地址)
printf("Sum: %d\n", pf(20, 10)); // 30
pf = Sub;
printf("Sub: %d\n", pf(20, 10)); // 10
return 0;
}
typedef int (*pfFun)(int, int);
int Execute(int a, int b, pfFun callback) {
return callback(a, b); // 將控制權交給調用者提供的函數
}
int main() {
printf("%d\n", Execute(20, 10, Sum)); // 30
printf("%d\n", Execute(20, 10, Sub)); // 10
return 0;
}
這就是回調模式:庫函數定義骨架,具體行為由調用者注入。
// 無 typedef:參數聲明冗長
void Register(int (*handler)(int, int));
// 有 typedef:清晰語義化
typedef int (*EventHandler)(int, int);
void Register(EventHandler handler);
typedef enum {ST_IDLE, ST_RUN, ST_STOP} State;
typedef void (*StateHandler)(void);
void IdleHandler() { printf("IDLE\n"); }
void RunHandler() { printf("RUNNING\n"); }
void StopHandler() { printf("STOPPED\n"); }
StateHandler table[] = {IdleHandler, RunHandler, StopHandler};
int main() {
State cur = ST_IDLE;
// 模擬事件驅動
cur = ST_RUN; table[cur]();
cur = ST_STOP; table[cur]();
return 0;
}
| 錯誤代碼 | 問題 | 修正 |
|---|---|---|
int *pf(int, int); | 聲明為「返回指針的函數」 | int (*pf)(int, int); |
pf = ∑ | 取地址符可省略,加上也合法但多餘 | 建議省略 & |
pf(20, 10); 未初始化 | 野指針調用 → 崩潰 | 賦值後再調用,或初始化為 NULL 並判空 |
| 簽名不匹配 | 未定義行為 | 嚴格匹配返回類型、參數類型、調用約定 |
#include <functional>
std::function f = [](int a, int b){ return a+b; };
f(3, 4); // 7
// 支持捕獲上下文、綁定成員函數、多態調用
C 語言環境下,函數指針仍是實現多態、插件、異步回調的基石。