在 C 语言中,函数也是一种“对象”,它在内存中有地址。因此可以定义指向函数的指针,用于动态调用、回调处理、构建函数表等。
掌握函数指针是理解 C 语言“底层抽象”与“模块化编程”的关键。
一、函数指针的基本概念
函数指针是一个变量,用于存储函数地址。通过它可以像调用普通函数一样间接调用函数。
示例:普通函数
int add(int a, int b) {return a + b;
}
函数名 add
实际就是函数在内存中的地址。
函数指针定义语法
返回类型 (*函数指针名)(参数类型1, 参数类型2, ...);
示例:定义与赋值
int (*fp)(int, int); // 定义指针
fp = add; // 或写成 fp = &add;
int result = fp(2, 3); // 间接调用函数
二、函数指针的使用场景
场景 | 描述 |
---|---|
回调机制 | 注册函数供其他代码异步调用 |
策略选择 | 多种处理方式中选择其一 |
接口抽象 | 封装模块细节 |
表驱动编程 | 构建函数数组替代大量 if/else |
三、函数指针数组
用于存储一组函数地址,实现快速查表式调用。
int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }int (*ops[2])(int, int) = {add, sub};
调用:
printf("%d\n", ops[0](5, 3)); // 输出 8
printf("%d\n", ops[1](5, 3)); // 输出 2
四、函数指针作为参数(回调函数)
将函数指针作为参数,实现在函数中回调用户传入的逻辑。
void compute(int x, int y, int (*op)(int, int)) {printf("Result: %d\n", op(x, y));
}
调用:
compute(10, 5, add); // 输出 15
compute(10, 5, sub); // 输出 5
五、typedef 简化函数指针声明
函数指针语法复杂,可以用 typedef
提高可读性。
typedef int (*Operation)(int, int);Operation op = add;
printf("%d\n", op(1, 2)); // 输出3
也适用于参数定义:
void compute(int x, int y, Operation f) {printf("%d\n", f(x, y));
}
六、返回函数指针的函数(高阶函数)
int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }typedef int (*OpFunc)(int, int);OpFunc getOp(char ch) {if (ch == '+') return add;else return sub;
}int main() {OpFunc f = getOp('+');printf("%d\n", f(3, 2)); // 输出5
}
七、使用函数指针实现菜单系统(实战)
#include <stdio.h>void show() { printf("Show\n"); }
void insert() { printf("Insert\n"); }
void del() { printf("Delete\n"); }void (*menu[])(void) = {show, insert, del};int main() {int choice;while (1) {printf("0: Show, 1: Insert, 2: Delete\n");scanf("%d", &choice);if (choice >= 0 && choice < 3)menu[choice]();elsebreak;}return 0;
}
八、函数指针 vs 一般指针
特性 | 一般指针(如 int*) | 函数指针 |
---|---|---|
指向类型 | 数据地址(变量、数组等) | 函数地址 |
赋值方式 | p = &a 或 p = arr | fp = func 或 fp = &func |
调用方式 | *p | fp(x, y) |
应用领域 | 数据访问 | 回调、策略、多态 |
九、常见错误和注意事项
错误类型 | 示例 | 正确方式 |
---|---|---|
忘记加括号 | int *f(int,int); | int (*f)(int,int); |
参数列表不匹配 | int (*f)(int); 用 f(1,2) 调用 | 确保参数类型和数量一致 |
未初始化直接调用 | int (*f)(int,int); f(1,2); | 调用前确保指针有效 |
误用数组下标超范围 | fp[3](); 超出数组范围 | 控制索引,避免越界 |
十、函数指针的实际意义
-
提高代码灵活性和可扩展性;
-
模拟面向对象的“多态”机制;
-
在驱动、GUI库、游戏引擎中广泛使用。
十一、总结
内容 | 说明 |
---|---|
定义函数指针 | int (*f)(int,int) |
指针数组 | int (*arr[])(int,int) |
回调函数 | 把函数指针作为参数 |
typedef 简化声明 | typedef int (*Op)(int,int) |
高阶函数 | 返回函数指针、构建策略函数 |
函数指针用途 | 回调机制、函数表、策略模式等 |