C语言 1000问 · 函数与递归Q3:函数指针是什么?它有哪些典型用途——回调、跳转表、qsort?
来源:Flomo 原始笔记|查看原笔记|迁移日期:2026-10-31
C语言 1000问 · 函数与递归Q3:函数指针是什么?它有哪些典型用途——回调、跳转表、qsort?
▎ 五大学习法:西蒙学习法——把「函数指针」钻透
函数指针是什么
- 函数在内存里也是一段代码、有入口地址;函数名在表达式中会退化成「函数指针」(指向该函数入口)。
- 声明:返回类型 (*名字)(参数类型…),例:int (*fp)(int, int); —— fp 是指向「int(int,int) 函数」的指针。
- 常见易错:int fp(int, int) 是「返回 int 的函数」;写成 (*fp) 才是函数指针,括号不能丢。
赋值与调用
- 赋值:fp = add; 或 fp = &add;(两者等价)。
- 调用:fp(2, 3); 或 (*fp)(2, 3);(也等价)。
典型用途
-
回调(callback):把函数指针传给库 / 框架,让它们回头调用你的代码。例:qsort 的 cmp 比较函数、事件注册、中断服务例程、异步完成通知。它让你在「不知道具体实现」的层里插入具体行为。
-
跳转表 / 分发表:用「函数指针数组」代替长串 if-else / switch。例:命令解释器、状态机——每个状态 / 命令对应一个函数指针,索引即查即调用;嵌入式里常用于协议命令处理表、按键处理表。
-
泛型 / 抽象接口:用函数指针模拟「虚函数」——结构体里放一组函数指针,就是 C 里的面向对象(vtable)。例:Linux 内核的 file_operations、struct device 的 ops。
-
高阶函数 / 策略注入:把算法策略当参数传入(排序比较、哈希函数、遍历动作)。
类型要点
- 类型必须精确匹配:返回类型、参数类型和个数都要一致,否则调用是 UB。
- 用 typedef 简化:typedef int ( cmp_t)(const void, const void*); 再用 cmp_t cmp。
- 函数指针可比较、可作参数 / 返回值、可放进结构体 / 数组。
- 大小:取决于平台(有的架构代码指针与数据指针宽度不同)。
嵌入式场景
- 中断向量表本质就是函数指针数组。
- 状态机、协议命令表、RTOS 任务表用函数指针数组。
- 注意:跳转表会阻止内联、影响优化;被调函数签名不匹配时严格检查会报错。
一个坑
- 函数指针指向的函数返回类型 / 参数不匹配时,编译可能只警告,运行是 UB——尤其跳转表里混用不同签名。
- 空指针调用、悬垂函数指针(指向已卸载模块)同样危险。
一句话:函数指针就是「把函数当数据来传」——核心用途是回调、跳转表、模拟虚函数;它让 C 能做泛型和高层抽象(qsort、内核 ops、中断向量表都是它)。
📎 问题库(专栏⑭导航)→ https://v.flomoapp.com/mine/?memo_id=MjQ1NzM0NTk5
📎 函数与递归Q2(递归 vs 迭代)→ https://v.flomoapp.com/mine/?memo_id=MjU2NDUwODMx