| 宣告 | 含義 | 口訣 |
|---|---|---|
int (*pfun)(int, int); | 函數指針:指向「接受兩 int、回傳 int」的函數 | 括號優先:*pfun 是指針 |
int *fun(int, int); | 指針函數:回傳 int* 的函數 | 無括號:fun 是函數 |
int max(int a, int b) { return a > b ? a : b; }
int min(int a, int b) { return a < b ? a : b; }
int main() {
int (*pfun)(int, int); // 宣告函數指針變數
pfun = max; // 賦值:函數名隱式轉址
int a = 3, b = 5;
printf("%d\n", pfun(a, b)); // 方式 1:直接調用
printf("%d\n", (*pfun)(a, b)); // 方式 2:解引用後調用(等價)
return 0;
}
typedef int (*Pfun)(int, int); // Pfun 成為「函數指針類型」 Pfun pfun = min; // 直接宣告變數 // 等價於:int (*pfun)(int, int) = min;
int do_operation(Pfun op, int a, int b) {
return op(a, b); // 呼叫傳入的函數
}
int main() {
printf("%d\n", do_operation(max, 10, 20)); // 30
printf("%d\n", do_operation(min, 10, 20)); // 10
return 0;
}
應用場景:qsort 比較函數、事件回調、狀態機狀態處理器、策略模式 C 實作。
C 無閉包,但可用 void* 上下文指標攜帶狀態:
typedef void (*Callback)(void* ctx, int event);
void on_click(void* ctx, int event) {
int* counter = (int*)ctx;
(*counter)++;
printf("Click %d\n", *counter);
}
void register_callback(Callback cb, void* ctx) {
// 模擬事件觸發
cb(ctx, 1);
cb(ctx, 2);
}
int main() {
int counter = 0;
register_callback(on_click, &counter);
return 0;
}
typedef struct { const char* name; Pfun func; } Command;
int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }
Command cmds[] = {
{"add", add},
{"sub", sub},
{NULL, NULL}
};
Pfun find_cmd(const char* name) {
for (int i = 0; cmds[i].name; ++i)
if (strcmp(cmds[i].name, name) == 0) return cmds[i].func;
return NULL;
}
int main() {
Pfun f = find_cmd("add");
if (f) printf("3+4=%d\n", f(3,4));
return 0;
}
__stdcall vs __cdecl 會導致堆疊破壞。(Pfun)func。if (pfun)。int cmp_int(const void* a, const void* b) {
return (*(int*)a - *(int*)b);
}
int arr[] = {5, 2, 9, 1, 3};
qsort(arr, 5, sizeof(int), cmp_int);
// arr 變為 {1,2,3,5,9}
qsort 接受 int (*compar)(const void*, const void*),這是函數指針實現泛型演算法的教科書級範例。
函數指針是 C 語言實現多態、回調、泛型演算法的核心機制。掌握 int (*pfun)(int, int) 宣告語法、typedef 簡化、void* 上下文傳遞、函數指針陣列分發四大模式,即可驾馭絕大多數 C 專案中的函數指針場景。記住:括號決定一切,類型必須精確匹配。