当前位置: 首页 > news >正文

[特殊字符]函数指针:C语言的动态灵魂,嵌入式的超能力(202589)

ccc函数指针:C语言的动态调度灵魂🌶️,嵌入式的超能力

参考教程::C函数指针;


//相当于`“策略模式”

一、函数指针定义

//基本形式:返回类型(*指针名)(参数列表)int (*MathOperations)(int , int);

二、函数指针的四大应用场景

2.1、📋 回调机制(异步通信的基石)
#include <iostream>
#include <cstring>using namespace std;//typedef定义HandleDataCallBack函数指针类型,用于实现“回调机制”
typedef void (*HandleDataCallBack)(const char *ptData, unsigned int size);   // 跨平台字符串复制实现
size_t GetDataInfo(char* buffer) {const char* testData = "Hello CallBack";size_t len = strlen(testData);// 添加边界检查if (len >= 1024) len = 1023;  // 防止缓冲区溢出// 跨平台安全复制#ifdef _WIN32// Windows 安全版本strncpy_s(buffer, 1024, testData, len);#else// Linux/Unix 标准版本strncpy(buffer, testData, len);#endifbuffer[len] = '\0';  // 确保字符串以 null 结尾return len;
}// 数据接收函数
void DataRecv(HandleDataCallBack dataHandle) {      //HandleDataCallBack dataHandlechar buf[1024] = {0};size_t actualSize = GetDataInfo(buf);if (dataHandle && actualSize > 0 && actualSize <= UINT_MAX) {dataHandle(buf, static_cast<unsigned int>(actualSize));}
}void ProcessData(const char *ptData, unsigned int size) {if (!ptData || size == 0) return;cout << "Received data: " << ptData << " (size: " << size << ")" << endl;
}int main() {cout << "=============== CallBack Function Show Start===============" << endl;DataRecv(ProcessData);cout << "=============== CallBack Function Show End===============" << endl;return 0;
}

💡 总结:核心设计模式

这段代码完美展示了 回调函数模式 的应用:

  • 解耦 :数据接收和数据处理逻辑分离
  • 灵活性 :可以动态更换不同的处理函数
  • 可扩展性 :易于添加新的数据处理逻辑

2.2、📋 策略模式(运行时的算法切换)

核心思想是把“算法”抽象成一个函数指针,然后在运行时根据 AlgoBitsFlag 的值动态地切换具体排序算法

// 排序算法接口
typedef void (*SortAlgo)(int *ptArr, int size);// 冒泡排序
void BubbleSort(int *ptArr, int size) { /* bubble sort */ };
// 插入排序
void InsertSort(int *ptArr, int size) { /* Insert sort */ };
// 快速排序
void QuickSort(int *ptArr, int size) { /* Quick sort */ };
// 希尔排序
void ShellSort(int *ptArr, int size) { /* Shell sort */ };
// 选择排序
void SelectSort(int *ptArr, int size) { /* Select sort */ };int AlgoBitsFlag = 0x0;// 执行排序
void ExecuteSort(SortAlgo algo, int *ptArr, int size)
{if (!ptArr || !size)return;algo(ptArr, size);
}int main()
{SortAlgo algo;int data[1024] = {0};// 动态选择排序算法if (AlgoBitsFlag & 0x1)algo = BubbleSort;else if (AlgoBitsFlag & 0x10)algo = InsertSort;else if (AlgoBitsFlag & 0x100)algo = QuickSort;else if (AlgoBitsFlag & 0x1000)algo = ShellSort;else if (AlgoBitsFlag & 0x10000)algo = SelectSort;elsealgo = QuickSort;ExecuteSort(algo, data, sizeof(data) / sizeof(data[0]));return 0;
}

💡 总结:策略模式(Strategy Pattern),

这段代码完美展示了 策略模式Strategy Pattern 的应用:

  • 开闭原则: 新增排序算法时,只需再写一个函数,把函数指针赋给 algo 即可,无需改动 ExecuteSort 或 main 里的流程代码。
  • 运行时灵活切换: 通过位掩码 AlgoBitsFlag 可以在程序运行期间随时决定用哪种算法,而不需要重新编译。
  • 调用方与算法解耦: ExecuteSort 只关心接口(函数指针),不关心具体实现,降低了模块间的耦合度,方便单元测试和替换实现。

2.3、📋 状态机切换(复杂流程控制)
#include <cstdio>
#include <thread>
#include <chrono>
#include <windows.h>// 前置声明
void CheckDeviceState();// 设备状态
typedef void (*DeviceState)(void);// 空闲态
void IdleState()
{printf("********** idle **********\n");
}// 运行态
void RunningState()
{printf("********** Running **********\n");
}// 故障态
void ErrorState()
{printf("********** error **********\n");
}// 状态机
typedef struct tagTDeviceState
{DeviceState state;
} TDeviceState;int OperationFlag = 0;// 检查并切换状态
void CheckDeviceState()
{TDeviceState current;current.state = IdleState;for (;;){current.state();// 简单事件:根据 OperationFlag 切状态if (OperationFlag == 0)current.state = RunningState;elsecurrent.state = ErrorState;std::this_thread::sleep_for(std::chrono::milliseconds(1000));}
}int main()
{// 解决中文乱码:把控制台代码页设为 UTF-8UINT oldcp = GetConsoleOutputCP();SetConsoleOutputCP(65001);std::thread worker(CheckDeviceState);char cmd;while (true){printf("\n输入 0 切运行态,输入非 0 切故障态,输入 q 退出:\n");std::scanf(" %c", &cmd);if (cmd == 'q' || cmd == 'Q')break;OperationFlag = (cmd == '0') ? 0 : 1;}// 恢复原来的代码页SetConsoleOutputCP(oldcp);worker.detach();return 0;
}

💡 总结:函数指针状态机

	♦️ 通过函数指针动态切换函数行为,实现状态切换;♦️ 使用多线程,实现异步状态检查和用户交互;

2.4、📋 C语言类实现
#include<stdio.h>// 学生结构体定义
// num: 学号
// score: 分数
// Func: 函数指针,用于指向打印学生信息的函数
typedef struct TStudent{int num;int score;void (*Func)(struct TStudent *);
}TStudent;// 打印学生信息函数
// ptStudent: 指向学生结构体的指针
void PrintStudent(TStudent *ptStudent){if (!ptStudent) return;  // 安全检查printf("num = %.5d, score = %d\n", ptStudent->num, ptStudent->score);
}// 创建学生对象函数
// num: 学号
// score: 分数
// 返回值: 初始化好的学生结构体
TStudent CreatStudent(int num,int score){TStudent student = {num,score, PrintStudent };  // 初始化结构体并设置函数指针return student;
}int main(void){// 创建学生对象TStudent student = CreatStudent(00001,100);// 通过函数指针调用打印函数student.Func(&student);return 0;
}

💡 总结:当前实现中 PrintStudent 函数作为成员函数指针使用,展示了面向对象思想在C语言中的实现方式

  • 灵活性: 通过函数指针 Func 成员,可以动态绑定不同的函数实现,实现运行时多态
  • 封装性: 将打印逻辑封装在 PrintStudent 函数中,通过指针调用,使代码更模块化;
  • 简洁性: 通过 student.Func(&student) 一行代码完成打印操作,调用方式直观简洁。

三、函数指针高级技巧

3.1 函数指针数组
#include<stdio.h>typedef int (*BoradPowerInitFunc)(void);// 三个独立的功能模块/*** @description: 电源启动* @return {*}*/
int  BoardPowerOn(){printf("Power On\n");   // 单一职责原则return 0;
}/*** @description: 注册* @return {*}*/
int Register(){printf("Register\n");   // 设备注册return 0;
}/*** @description: 参数配置* @return {*}*/
int ParaConfig(){printf("ParaConfig\n");  // 模块化设计return 0; 
}BoradPowerInitFunc InitTable[]={BoardPowerOn,     // 可自由调整顺序Register,         // 方便增删模块ParaConfig,       // 拓展性强
};int main(){for(int i = 0; i < sizeof(InitTable) / sizeof(InitTable[0]); i++){InitTable[i]();}return 0;
}

💡 总结:通过==函数指针数组实现模块化的初始化流程管理==;

  • 模块化设计:各功能符合单一职责原则;
  • 流程标准化:通过BoradPowerInit实现统一函数签名,确保接口一致性;
  • 集中管理 :初始化步骤在函数指针数组中显式声明配置,与执行逻辑解耦;

【💻提升:多板初始化配置】

在这里插入图片描述

#include <stdio.h>typedef int (*BoradPowerInitFunc)(void);/* 单板初始化配置结构体* @成员说明:*   BoardName      - 单板硬件名称 *   BoardType      - 单板类型编码(0x01~0x03)*   BoardStatsus   - 状态寄存器(0xff表示未初始化状态)*   BoardPowerInit - 硬件上电初始化入口函数*   Register       - 操作系统注册接口*   ParaConfig     - 个性化参数配置接口 */
typedef struct tagBoardInitConifg{const char *BoardName;              int BoardType;                      int BoardStatsus;                   BoradPowerInitFunc BoardPowerInit;  int (*Register)(void);              int (*ParaConfig)(void);            
}TBoardInitConfig;// 单板A初始化函数(返回0表示成功)
int BoardA_Init()   
{printf("BoardA_Init...\n");return 0;
}// 单板B初始化函数(返回0表示成功)
int BoardB_Init()  
{printf("BoardB_Init...\n");  return 0;
}// 单板C初始化函数(返回0xFF表示初始化失败
int BoardC_Init()   
{printf("BoardC_Init...\n");  return 0xff;
}   //单板向操作系统注册
int OssRegister(){printf("OssRegister\n");return 0;
}int BoardA_ParaCfg(){printf("BoardA_Register\n");return 0;
}int BoardB_ParaCfg(){printf("BoardB_Register\n");return 0; 
}int BoardC_ParaCfg(){printf("BoardC_Register\n"); return 0; 
}//✨板初始化表
TBoardInitConfig BoardInitTable[] = {
// 参数说明:名称 | 类型 | 状态 | 初始化函数 | 注册接口 | 配置接口{"Board_A", 0x01, 0xff, BoardA_Init, OssRegister, BoardA_ParaCfg},{"Board_B", 0x02, 0xff, BoardB_Init, OssRegister, BoardB_ParaCfg}, {"Board_C", 0x03, 0xff, BoardC_Init, OssRegister, BoardC_ParaCfg},{NULL, 0xff, 0xff, NULL, NULL, NULL}   // 结束标记
};int main(){TBoardInitConfig *pBoardInitTable = BoardInitTable;/* 初始化流程控制逻辑* 1. 遍历所有单板配置* 2. 执行三级初始化流程:*    - 电源初始化 → 信息打印 → 注册 → 参数配置* 3. 支持初始化失败处理(当前仅跳过失败单板) */while(pBoardInitTable->BoardName != NULL){int result = pBoardInitTable->BoardPowerInit();   // 执行单板上电初始化if(result == 0x0){printf("Board %s Init Success, Result Code: 0x%x\n", pBoardInitTable->BoardName, result); // 打印单板基础信息printf("Board Name:   %s\n", pBoardInitTable->BoardName);  printf("Board Type:   %d\n", pBoardInitTable->BoardType);printf("Board Status: 0x%x\n", pBoardInitTable->BoardStatsus); // 执行后续初始化步骤pBoardInitTable->Register();pBoardInitTable->ParaConfig();printf("\n");}else{printf("Board %s Init Failed, Result Code: 0x%x\n", pBoardInitTable->BoardName, result);printf("\n"); }pBoardInitTable++;  // 指针移动到下一个单板配置}return 0;
}

3.2 返回函数指针的函数
#include <stdio.h>// 定义函数指针类型,用于统一接口的数学运算操作
typedef int(*Operation)(int, int);int add(int a, int b){ return a + b; }
int subtract(int a, int b){ return a - b; }
int multiply(int a, int b){ return a * b; }
int divide(int a, int b){ return a / b ? : a / b , 0; }// 工厂函数:根据操作符返回对应的运算函数
Operation CalcResult(char ch){switch(ch){case '+': return add;case '-': return subtract;case '*': return multiply;case '/': return divide;default: return NULL;}
}int main(){Operation op = CalcResult('+');    //返回函数指针if(op){int result = op(10, 5);printf("Result: %d\n", result); }    return 0;
}

💡 总结:简单工厂模式

  • 接口抽象化:通过Operation函数指针类型统一了所有算术操作的调用接口,符合面向接口编程思想
  • 开闭原则:新增运算操作只需添加函数实现和case分支,无需修改现有代码(如扩展取模运算)
  • 解耦设计:业务逻辑(main)与具体运算实现分离,CalcResult作为工厂方法隔离了对象创建细节
  • 类型安全:使用typedef明确定义函数指针类型,增强代码可读性和类型安全性
  • 防御式编程:main函数中检查空指针,避免无效操作符导致的运行时错误
  • 可扩展性:运算函数都是无状态纯函数,方便后续扩展为多线程/分布式计算
  • 代码复用:相同调用方式处理不同运算,减少重复代码(如后续添加更多运算符时)
  • 维护友好:每个运算函数保持独立,方便单独测试和修改实现细节


四、性能分析

结论✨:函数指针与直接调用函数方式的**开销差距较小,但架构优势明显**

http://www.dtcms.com/a/423863.html

相关文章:

  • 海口网站建设高端asp.net做电商网站
  • C++ 面向对象进阶:继承深化与多态详解
  • 达建网站长沙网站快速排名优化
  • 网站浏览器兼容性问题吗产品介绍网站源码
  • 20.Nginx 服务器
  • CTFshow萌新杂项详细解题攻略及学习笔记
  • jsp网站服务器如何做防护飘云网络科技有限公司
  • Effective Python 第34条: 避免使用 `send()` 给生成器注入数据
  • wordpress站内301上海对外经贸大学
  • 当AI助手“记忆混乱”:理解与应对Roo Code的上下文污染问题
  • Docker 网络详解:(二)虚拟网络环境搭建与测试
  • 【Docker】在项目中如何实现Dockerfile 文件编写
  • 专门做任务的网站吗wordpress数据库文件
  • AMD KFD的BO设计分析系列5-3:VM-amdgpu_bo_va_mapping
  • FilterSolutions2019使用指南
  • 方寸控股解读:《工业园区高质量发展指引》下的园区升级路径
  • 学习总结——接口测试基础
  • 好的案例展示网站在线设计平台招募设计师
  • 阳泉网站建设哪家便宜上海哪家公司提供专业的网站建设
  • TCP的理解
  • 鸿蒙应用主题模式切换实现详解
  • Matplotlib `imsave()` 函数详解
  • NFC技术如何破解电子制造领域的效率瓶颈与追溯难题
  • sk06.【scikit-learn基础】--『监督学习』之决策树
  • 银川怎么做网站wordpress炫酷站
  • 网站说明页命名大连响应式网站建设
  • 程序综合实践第二次递归与dfs
  • 半双工 vs 全双工:对讲机与电话的根本区别
  • 华茂达建设集团网站公司注册网上核名业务如何终止
  • 从虚拟背景到绿幕替换:人像分割功能在直播美颜sdk中的落地应用