22. 回调函数与函数指针:让你的嵌入式代码像乐高积木一样灵活拼接

📅 2026/7/4 3:57:03 👤 编程新知 🏷️ 技术资讯
22. 回调函数与函数指针:让你的嵌入式代码像乐高积木一样灵活拼接 函数指针的定义与使用函数指针本质是存储函数内存地址的变量其定义遵循特定语法规则返回值类型 (*指针变量名)(参数类型列表);例如指向无返回值且带一个整型参数的函数指针void (*callback)(int);赋值时直接使用函数名函数名即地址void handler(int val) { /*...*/ } callback handler; // 合法赋值 callback handler; // 等效写法回调函数的解耦实现典型回调模式包含三个要素回调接口定义函数指针类型回调注册机制触发执行逻辑以定时器中断为例的完整实现// 1. 定义回调类型 typedef void (*TimerCallback)(void* context); // 2. 注册结构体 typedef struct { TimerCallback cb; void* context; } TimerEvent; TimerEvent g_timer_event; void Timer_RegisterCallback(TimerCallback cb, void* ctx) { g_timer_event.cb cb; g_timer_event.context ctx; } // 3. 中断服务函数中触发 void TIMx_IRQHandler() { if (g_timer_event.cb) { g_timer_event.cb(g_timer_event.context); } // 清除中断标志... }面向对象式封装通过结构体封装多个函数指针实现类似C的接口抽象// 存储驱动接口定义 typedef struct { int (*init)(void* config); int (*read)(uint8_t* buffer); int (*write)(const uint8_t* data); } StorageDriver; // SPI Flash具体实现 static int SPI_Flash_Init(void* config) { /*...*/ } static int SPI_Flash_Read(uint8_t* buf) { /*...*/ } // 驱动实例化 const StorageDriver spi_flash { .init SPI_Flash_Init, .read SPI_Flash_Read, .write NULL // 本例为只读设备 }; // 文件系统层调用 void Filesystem_Mount(const StorageDriver* driver) { driver-init(NULL); uint8_t buf[256]; driver-read(buf); }实际工程应用场景硬件抽象层HALSTM32的HAL_UART_RegisterCallback()ESP-IDF的driver_install()注册事件回调协议栈处理LWIP的netconn_recv()设置数据接收回调MQTT客户端的消息到达回调状态机实现typedef void (*StateHandler)(void); StateHandler current_state; void Idle_State(void) { /*...*/ } void Working_State(void) { /*...*/ } void Run_Machine(void) { current_state(); // 执行当前状态处理 }注意事项与最佳实践始终检查指针非空if(callback) callback();使用typedef提高可读性typedef int (*Comparator)(int, int); Comparator comp /*...*/;避免多层回调嵌套回调地狱可通过状态机分解在RTOS中注意跨任务回调时的线程安全问题调试技巧使用函数指针转译工具查看实际调用点printf(Callback at %p\n, (void*)callback);通过backtrace工具追踪回调调用链在gdb中使用info symbol addr查询函数指针指向