除指向数据的指针外,C 语言还支持函数指针:保存函数入口地址,并通过指针间接调用函数。当需要在运行时选择不同的函数实现(例如不同的比较规则)时,函数指针是常用手段。
为何使用函数指针
直接写函数名调用即可满足多数需求。若调用方(如标准库排序)只提供统一接口,而具体行为由程序员提供,则可将函数地址作为参数传入。典型例子是 qsort 的比较函数。
声明方式
void (*pf)(int);含义可理解为:pf 是指针,指向“接受一个 int 参数、返回 void”的函数。*pf 两侧的括号不可缺少;若省略,声明将变为返回指针的函数,语义不同。
char *(*pf)(int *);
/* pf 指向的函数:参数为 int *,返回 char * */赋值与调用
函数名在表达式中可转换为函数指针;也可显式使用 & 取地址:
#include <stdio.h>
void someFunction(int arg) {
printf("someFunction 被调用,参数是 %d\n", arg);
}
int main(void) {
void (*pf)(int);
pf = someFunction; /* 或 pf = &someFunction; */
pf(5);
return 0;
}示例:qsort 与自定义比较函数
#include <stdio.h>
#include <stdlib.h>
int compare(const void *left, const void *right) {
return *(int *)right - *(int *)left; /* 降序 */
}
int main(void) {
int iarray[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int n = (int)(sizeof(iarray) / sizeof(iarray[0]));
qsort(iarray, n, sizeof(int), compare);
for (int i = 0; i < n; i++) {
printf("%d ", iarray[i]);
}
printf("\n");
return 0;
}更换比较函数即可改变排序规则,而无需修改 qsort 的实现。
函数指针数组
可将多个函数指针存入数组,按索引选择调用,常用于菜单、状态机等:
#include <stdio.h>
void f1(int var) { printf("f1,参数 %d\n", var); }
void f2(int var) { printf("f2,参数 %d\n", var); }
void f3(int var) { printf("f3,参数 %d\n", var); }
int main(void) {
void (*funcs[3])(int) = {f1, f2, f3};
for (int c = 0; c < 3; c++) {
funcs[c](c);
}
return 0;
}常见应用场景
- 标准库回调:排序、查找等接口传入比较或处理函数。
- 事件驱动或异步逻辑中的回调函数。
- 命令表、状态机:用函数指针数组映射编号与处理函数。
理解函数指针有助于阅读标准库与第三方 API 中“传入函数地址”的接口;其语法与指针基础密切相关。