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);(也等价)。

典型用途

  1. 回调(callback):把函数指针传给库 / 框架,让它们回头调用你的代码。例:qsort 的 cmp 比较函数、事件注册、中断服务例程、异步完成通知。它让你在「不知道具体实现」的层里插入具体行为。

  2. 跳转表 / 分发表:用「函数指针数组」代替长串 if-else / switch。例:命令解释器、状态机——每个状态 / 命令对应一个函数指针,索引即查即调用;嵌入式里常用于协议命令处理表、按键处理表。

  3. 泛型 / 抽象接口:用函数指针模拟「虚函数」——结构体里放一组函数指针,就是 C 里的面向对象(vtable)。例:Linux 内核的 file_operations、struct device 的 ops。

  4. 高阶函数 / 策略注入:把算法策略当参数传入(排序比较、哈希函数、遍历动作)。

类型要点

  • 类型必须精确匹配:返回类型、参数类型和个数都要一致,否则调用是 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

C语言