函数结构体应用实例

发布时间:2026/8/16 12:45:41
函数结构体应用实例 一、函数结构体使用的优点适用场景裸机 / RT‑Thread 嵌入式 C99 开发STM32 项目常用用结构体保存成员数据 函数指针保存操作接口实现 C 语言伪面向对象。1. 数据和行为聚合高内聚普通写法全局变量分散、功能函数独立 结构体把模块状态数据和操作该数据的函数接口打包在一起。相关变量、操作集中管理阅读代码一眼看懂模块有什么数据、能做什么动作。避免大量零散全局变量减少全局命名污染。2. 支持实例化一套代码多个对象最大优势之一结构体可以定义多个实例。 例如一个继电器驱动结构体可以实例化 relay1、relay2共用同一套函数实现只各自保存独立状态。如果用全局变量写驱动要复制多份全局代码大量重复维护灾难。ModuleObj_t dev1; ModuleObj_t dev2; dev1.init(); dev2.init();3. 接口隐藏、封装信息隐藏头文件只暴露结构体前向声明不展开内部成员内部数据私有化外部不能直接访问内部变量只能调用提供的函数指针接口读写外部只能调用对外提供接口禁止直接修改内部状态防止外部乱改成员造成状态异常内部实现改动只要接口函数指针原型不变上层业务代码完全不用修改。4. 多态便于适配不同硬件 / 型号非常适合 STM32 多芯片兼容F407/F030、不同外设硬件适配。相同函数接口原型底层绑定不同实现上层调用完全一致。 举例obj.init drv_f030_init; //F030版本底层实现 //obj.init drv_f407_init;//F407版本底层实现 obj.init();//上层调用代码无需改动可以做到上层业务逻辑一套底层硬件实现按需替换配合条件编译完成多型号适配。5. 降低耦合分层清晰上层业务只操作对象结构体接口不需要依赖底层具体函数名。底层驱动修改、BUG 修复只要接口签名不变业务层代码不用改动。便于模块解耦模块之间只传对象句柄结构体指针不互相引用大量全局。6. 便于单元测试、模拟 mock测试的时候可以把结构体里函数指针替换成模拟 mock 函数不需要真实硬件就可以测试上层业务逻辑。 比如把硬件读写函数指针替换成仿真函数PC 上即可做模块单元测试。二、对应的缺点工程需要权衡有少量内存开销每个实例会占用若干函数指针4 字节 / 个32 位 MCU实例很多时要关注 RAM 占用调试难度略上升函数指针跳转Keil 断点不能直接跳进实现需要看指针指向的真实函数对开发人员要求高错误赋值函数指针会直接跑 HardFault必须严格做参数校验C 语言本身没有访问控制语法“私有” 依靠编码约定强制前向声明才能真正禁止外部访问结构体内部。三、对比普通全局函数 全局变量 vs 结构体函数指针表格维度全局变量 普通函数结构体 函数指针多实例需要复制多份全局重复代码直接定义多个结构体实例封装性外部可随意修改全局变量可隐藏内部成员仅接口访问耦合度业务层硬编码调用底层函数名依赖抽象接口底层可替换多态适配大量 #ifdef 分散业务代码同一套上层底层替换函数指针内存占用全局永久占用 RAM实例按需分配多几个指针开销调试直接断点函数指针间接跳转调试稍麻烦四、应用实例led灯控制初始化、亮、灭、翻转、短暂闪烁、获取当前状态。#ifndef _DEV_LEDRUN_H #define _DEV_LEDRUN_H //----------------------------------------------- // 枚举定义 //----------------------------------------------- typedef enum { LED_RUN_OFF 0, // 灯灭 LED_RUN_ON 1, // 灯亮 } LedRun_StateEnum; //----------------------------------------------- // 接口结构体 //----------------------------------------------- typedef struct { void (*Init)(void); // 初始化 void (*SetOn)(void); // 亮 void (*SetOff)(void); // 灭 void (*Toggle)(void); // 翻转 void (*Blink_Short)(uint8_t times); // 短暂闪烁可设次数 LedRun_StateEnum (*GetState)(void); // 获取当前状态 } LedRun_OpTypeDef; typedef struct { LedRun_StateEnum currentState; const LedRun_OpTypeDef op; } LedRun_DeviceTypeDef; extern LedRun_DeviceTypeDef dev_LedRun; #endif//---------------------------------------------------------------------- //描述: 运行指示灯接口配置与使用源文件 //---------------------------------------------------------------------- #include Dev_LedRun.h //----------------------------------------------- // 运行灯引脚定义 //----------------------------------------------- #define LED_RUN_PORT GPIOC #define LED_RUN_PIN GPIO_Pin_15 #define LED_RUN_CLK RCC_AHBPeriph_GPIOC //----------------------------------------------- // 内部函数声明 //----------------------------------------------- static void LedRun_Init(void); static void LedRun_SetOn(void); static void LedRun_SetOff(void); static void LedRun_Toggle(void); static void LedRun_Blink_Short(uint8_t times); static LedRun_StateEnum LedRun_GetState(void); //----------------------------------------------- // 对外设备实例C99 //----------------------------------------------- LedRun_DeviceTypeDef dev_LedRun { .currentState LED_RUN_OFF, .op { .Init LedRun_Init, .SetOn LedRun_SetOn, .SetOff LedRun_SetOff, .Toggle LedRun_Toggle, .Blink_Short LedRun_Blink_Short, .GetState LedRun_GetState, } }; //----------------------------------------------- // 函数实现 //----------------------------------------------- //---------------------------------------------------------------------- //函数功能: 运行灯初始化 //参数: 无 //返回值: 无 //备注: PB10推挽输出默认灯灭 //---------------------------------------------------------------------- static void LedRun_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; RCC_AHBPeriphClockCmd(LED_RUN_CLK, ENABLE); GPIO_InitStruct.GPIO_Pin LED_RUN_PIN; GPIO_InitStruct.GPIO_Mode GPIO_Mode_OUT; GPIO_InitStruct.GPIO_OType GPIO_OType_PP; GPIO_InitStruct.GPIO_Speed GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_PuPd GPIO_PuPd_NOPULL; GPIO_Init(LED_RUN_PORT, GPIO_InitStruct); LedRun_SetOff(); } //---------------------------------------------------------------------- //函数功能: 灯常亮低电平点亮 //---------------------------------------------------------------------- static void LedRun_SetOn(void) { GPIO_WriteBit(LED_RUN_PORT, LED_RUN_PIN, Bit_RESET); dev_LedRun.currentState LED_RUN_ON; } //---------------------------------------------------------------------- //函数功能: 灯常灭高电平熄灭 //---------------------------------------------------------------------- static void LedRun_SetOff(void) { GPIO_WriteBit(LED_RUN_PORT, LED_RUN_PIN, Bit_SET); dev_LedRun.currentState LED_RUN_OFF; } //---------------------------------------------------------------------- //函数功能: 电平翻转 //---------------------------------------------------------------------- static void LedRun_Toggle(void) { if(dev_LedRun.currentState LED_RUN_ON) LedRun_SetOff(); else LedRun_SetOn(); } //---------------------------------------------------------------------- //函数功能: 短暂闪烁可设置次数 //参数: times: 闪烁次数 //---------------------------------------------------------------------- static void LedRun_Blink_Short(uint8_t times) { uint8_t i; if(times 0) return; for(i 0; i times; i) { LedRun_SetOn(); delay_ms(60); LedRun_SetOff(); delay_ms(60); } } //---------------------------------------------------------------------- //函数功能: 获取当前灯状态 //---------------------------------------------------------------------- static LedRun_StateEnum LedRun_GetState(void) { return dev_LedRun.currentState; }

相关新闻