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

深度解析回調函數:從函數指針到實戰應用模式

     編輯:關於C

什麼是回調函數?

**回調函數** = 通過函數指針調用的函數。當你把一個函數的地址作為參數傳給另一個函數,並在後者內部通過該指針調用前者時,這個被調用的函數就是回調函數。

基礎概念鏈:指針函數 → 函數指針 → 回調函數

概念聲明示例含義
普通函數int func(int x);返回 int 的函數
指針函數int* func(int x);返回 int* 的函數
函數指針int (*fp)(int x);指向「接受 int、返回 int 的函數」的指針變量

代碼區同樣佔用內存,有首地址。fp = func; 將函數入口地址賦給指針,隨後可通過 fp(args) 調用。

為什麼需要回調?核心價值:解耦

  • 調用者不關心具體實現,只依賴函數簽名(原型)。
  • 被調用者(庫/框架)不關心業務邏輯,只負責調度。
  • 實現控制反轉 (IoC):框架調用用戶代碼,而非用戶調用框架。

經典應用場景

  1. 通用算法庫:qsort 接受比較函數指針,實現任意類型排序。
  2. 事件通知/異步回調:SetTimer、信號處理、GUI 事件循環、網絡 I/O 完成通知。
  3. 插件/擴展架構:宿主程序註冊回調,插件實現具體行為(如 FreeRDP 繪圖後端)。

實戰:通用冒泡排序 + 回調比較器

[c]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* 回調函數類型:比較兩個 void* 元素 */
typedef int (*CompFunc)(void* ctx, void* a, void* b);

/* 通用冒泡排序:對 void** 數組排序 */
int bubble_sort(void** array, int len, CompFunc cmp, void* ctx) {
    if (!array || !cmp) return -1;
    for (int i = len - 1; i > 0; i--) {
        for (int j = 1, max = 0; j <= i; j++) {
            if (cmp(ctx, array[j], array[max]) > 0) max = j;
            if (max != i) {
                void* tmp = array[max];
                array[max] = array[i];
                array[i] = tmp;
            }
        }
    }
    return 0;
}

/* 升序比較器 */
int cmp_asc(void* ctx, void* a, void* b) {
    return *(int*)a - *(int*)b;
}

/* 降序比較器 */
int cmp_desc(void* ctx, void* a, void* b) {
    return *(int*)b - *(int*)a;
}

/* 測試 */
int main() {
    int n = 10;
    void** arr = malloc(n * sizeof(void*));
    int* data = malloc(n * sizeof(int));
    for (int i = 0; i < n; i++) {
        data[i] = rand() % 100;
        arr[i] = &data[i];
        printf("%d ", data[i]);
    }
    puts("");

    bubble_sort(arr, n, cmp_asc, NULL);
    for (int i = 0; i < n; i++) printf("%d ", *(int*)arr[i]);
    puts("");

    bubble_sort(arr, n, cmp_desc, NULL);
    for (int i = 0; i < n; i++) printf("%d ", *(int*)arr[i]);
    puts("");

    free(arr); free(data);
    return 0;
}

C 與 C++ 的選擇建議

  • C 語言:回調函數是實現多態、泛型的核心手段,大量使用(如 qsort, bsearch, pthread_create)。
  • C++:優先使用虛函數(繼承多態)、函數對象、Lambda、std::function。僅在對接 C 庫、舊有回調接口時使用函數指針回調。

FreeRDP 實戰啟示

FreeRDP 將所有繪圖操作抽象為回調接口(rdpGraphics)。移植到新圖形庫(如 Skia)時,只需實現這些回調函數並註冊,**無需理解整個 RDP 協議流程**,極大降低了移植複雜度。這正是「面向接口編程」+「依賴倒置」的經典體現。

總結

回調函數本質是將「做什麼」與「怎麼做」分離。掌握函數指針語法、理解調用約定、設計清晰的回調原型(含上下文指針 void* ctx 傳遞狀態),是系統級 C 開發的核心技能。

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