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

C語言高級編程:函數指針深度解析與應用

     編輯:關於C

函數指針本質

函數指針指向代碼區(指令內存),普通指針指向數據區。函數名本身就是函數入口地址。

聲明語法

返回類型 (*指針變量名)(參數列表);
// 例:void (*pf)();  // 指向 void f() 類型函數

基本使用示例

void open()  { printf("open\n"); }
void print() { printf("print\n"); }
void exit()  { printf("exit\n"); }

int main() {
    // 1. 單個函數指針
    void (*pf)() = open;
    (*pf)();  // 調用 open()

    // 2. 函數指針數組:菜單/狀態機核心
    void (*pfs[])() = {open, print, exit};
    for (int i = 0; i < 3; i++)
        (*pfs[i])();  // 依次調用 open, print, exit
}

複雜聲明讀法:右左法則

從變量名開始,先右後左,遇括號優先處理括號內。

案例解析

聲明含義讀法步驟
void (*getInterrupt(int no))();函數聲明:參數 int,返回指向 void() 的指針getInterrupt → (int no) → * → () → void
void setInterrupt(int no, void (*pf))();函數聲明:參數 int 和函數指針,返回 voidsetInterrupt → (int no, *pf()) → void
LRESULT (*lpfnWndProc)(HWND, UINT, WPARAM, LPARAM);變量聲明:指向窗口過程函數的指針lpfnWndProc → * → (HWND...) → LRESULT

實戰應用場景

1. 回調函數:qsort 比較器

int cmp_int(const void *a, const void *b) {
    return *(int*)a - *(int*)b;
}
qsort(arr, n, sizeof(int), cmp_int);  // 標準庫回調

2. 狀態機/事件驅動

typedef void (*StateHandler)(Event*);
StateHandler state_table[] = {
    [IDLE] = handle_idle,
    [RUNNING] = handle_running,
    [ERROR] = handle_error
};
// 運行時動態分發
state_table[current_state](&event);

3. 插件/擴展架構

// 宿主程序
typedef struct { const char *name; void (*init)(); void (*run)(); } Plugin;
Plugin plugins[MAX_PLUGINS];

// 插件實現(單獨編譯)
void my_plugin_init() { ... }
void my_plugin_run() { ... }
Plugin my_plugin = {"MyPlugin", my_plugin_init, my_plugin_run};

4. 面向對象模擬:虛函數表

typedef struct {
    void (*draw)(Shape*);
    double (*area)(Shape*);
} ShapeVTable;

typedef struct {
    ShapeVTable *vptr;
    // 數據成員...
} Shape;

// 繼承:子類填寫自己的 vtable
ShapeVTable circle_vtable = {circle_draw, circle_area};
Shape circle = {&circle_vtable, ...};

// 多態調用
shape->vptr->draw(shape);

typedef 簡化聲明

// 不用 typedef
void (*signal(int sig, void (*handler)(int)))(int);

// 使用 typedef
typedef void (*SigHandler)(int);
SigHandler signal(int sig, SigHandler handler);  // 清晰得多

避坑指南

  • 調用語法: (*pf)() 或 pf() 均可,前者更明確
  • 兼容性: 指針類型必須與函數簽名完全匹配(返回值、參數、調用約定)
  • NULL 檢查: 調用前務必 if (pf) (*pf)();
  • 不要混淆: int *f()(返回指針的函數)vs int (*f)()(函數指針)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved