函數指針是 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); // 調用:像普通函數一樣用
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); // 按年齡排
typedef int (*PFUNC)(int, int); 讓指針類型可讀性提升 100%qsort 正是此模式的工業級實現掌握函數指針,是從「寫代碼」進階到「設計框架」的分水嶺。