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

C 語言函數指針完整指南:宣告、調用、回調與類型定義實戰

     編輯:關於C語言

函數指針 vs 指針函數:一眼分辨

宣告含義口訣
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 簡化複雜宣告

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;
}

常見錯誤與避坑

  1. 參數不匹配:指針類型必須與目標函數簽名完全一致(含呼叫慣例)。
  2. 調用慣例不符:Windows __stdcall vs __cdecl 會導致堆疊破壞。
  3. 隱式轉換警告:嚴格模式下需顯式轉型 (Pfun)func。
  4. NULL 指針調用:調用前務必檢查 if (pfun)。

標準庫經典案例:qsort

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 專案中的函數指針場景。記住:括號決定一切,類型必須精確匹配。

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