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

C語言第十一課:函數指針、回調機制與動態排序實戰

     編輯:關於C語言

C語言第十一課:函數指針、回調機制與動態排序實戰

函數指針是 C 語言實現「策略模式」「回調」「動態多態」的核心武器。本課通過三個遞進案例,從語法到實戰,徹底掌握函數指針精髓。

一、函數指針基礎:定義、賦值、調用

核心認知: 函數名 = 函數入口地址 = 指針常量,存放在代碼段。

int maxValue(int a, int b) { return a > b ? a : b; }
int sumValue(int a, int b) { return a + b; }

// 定義函數指針:返回 int,參數 (int, int)
int (*funcPtr)(int, int) = NULL;

funcPtr = maxValue;      // 賦值:函數名即地址
int result = funcPtr(3, 5);  // 調用:像普通函數一樣用

案例:用戶輸入決定調用 max 還是 sum

int main() {
    int a, b; char op[10];
    scanf("%d %d", &a, &b);
    scanf("%s", op);  // 輸入 "max" 或 "sum"
    
    int (*p)(int, int) = NULL;
    if (strcmp(op, "max") == 0) p = maxValue;
    else if (strcmp(op, "sum") == 0) p = sumValue;
    
    printf("Result: %d\n", p(a, b));  // 統一調用入口
    return 0;
}

二、回調函數:把函數作參數傳遞

場景: 通用查找函數,匹配邏輯由調用者決定。

// 結構體定義
typedef struct { char name[20]; int age; float score; } Student;

// 回調類型:輸入 Student*,返回 BOOL(是否符合條件)
typedef BOOL (*MatchFunc)(Student *);

// 通用查找:遍歷數組,符合條件者執行 action 回調
void findStudent(Student *stu, int count, MatchFunc match, void (*action)(Student *)) {
    for (int i = 0; i < count; i++) {
        if (match(&stu[i])) action(&stu[i]);
    }
}

// 具體匹配:分數 >= 90
BOOL isHighScore(Student *s) { return s->score >= 90; }

// 具體動作:名字後綴 "高富帥"
void appendTag(Student *s) { strcat(s->name, " 高富帥"); }

// 使用
findStudent(students, n, isHighScore, appendTag);

三、動態排序:比較策略外部化

痛點: 排序邏輯固化在代碼中,需求變更(按分數/年齡/名字排)需改代碼重編譯。
解法: 比較函數指針化,運行時注入策略。

// 通用冒泡排序:元素類型 void*,比較函數指針決定大小關系
void sortArray(void *base, int count, size_t size, int (*cmp)(const void *, const void *)) {
    char *arr = (char *)base;
    for (int i = 0; i < count - 1; i++)
        for (int j = 0; j < count - 1 - i; j++)
            if (cmp(arr + j * size, arr + (j+1) * size) > 0) {
                // 交換兩個元素(按字節拷貝)
                for (size_t k = 0; k < size; k++) {
                    char tmp = arr[j*size + k];
                    arr[j*size + k] = arr[(j+1)*size + k];
                    arr[(j+1)*size + k] = tmp;
                }
            }
}

// 比較函數:按分數降序
int cmpScore(const void *a, const void *b) {
    Student *s1 = (Student *)a, *s2 = (Student *)b;
    return (s2->score > s1->score) - (s2->score < s1->score);  // 避免浮點減法溢出
}

// 比較函數:按年齡升序
int cmpAge(const void *a, const void *b) {
    Student *s1 = (Student *)a, *s2 = (Student *)b;
    return s1->age - s2->age;
}

// 使用:同一排序函數,不同策略
sortArray(students, n, sizeof(Student), cmpScore);  // 按分數排
sortArray(students, n, sizeof(Student), cmpAge);    // 按年齡排

關鍵點總結

  1. typedef 簡化聲明:typedef int (*PFUNC)(int, int); 讓指針類型可讀性提升 100%
  2. 回調 = 控制反轉:框架代碼調用業務代碼,實現高內聚低耦合
  3. qsort 原理即此:標準庫 qsort 正是此模式的工業級實現
  4. 函數指針兼容性:參數、返回類型必須嚴格匹配,否則未定義行為

掌握函數指針,是從「寫代碼」進階到「設計框架」的分水嶺。

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