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

C扩展4:X宏(X-MACRO)

        代码从.c到可执行文件.elf/.exe会一次经历预编译、编译、汇编、链接四个阶段,而预编译过程中一个很重要的动作就是进行宏替换,所以可以利用这个阶段​​自动化地生成重复性的代码结构​​,特别是在处理​​协议字段、驱动注册、配置表​​等需要大量相似定义的场景。

        思想是:​​通过宏和X-Macro模式,将一份“数据定义”同时用于生成枚举、结构体数组等多种数据结构,保证唯一数据源,减少重复和错误。​
想象一个场景:你需要定义一组命令码或协议字段。通常你需要:
1.定义一个枚举(enum),给每个字段一个唯一的ID。
2.定义一个结构体数组,存放每个字段的处理函数和参数。
传统做法是写两份列表,很容易出现两个列表不同步的错误。而这组宏的终极目标就是:​​你只定义一份列表,宏自动帮你生成枚举和结构体数组​​。

#define DEF(a,b) a         
int m = DEF(1,2);        
#undef DEF                 
#define DEF(a,b) b          
int n = DEF(1,2);           

从宏的定义和取消来控制想要的输出,于是:

#define CMD_FUN                       \DEF(UP, up_func)          \DEF(DOWN, down_func)      \DEF(LEFT, left_func)      \DEF(RIGHT, right_func)    \

enum定义

typedef enum
{#define DEF(a,b) a,CMD_FUN#undef DEFCMD_END
};

在编译之后就变为

typedef enum
{UP, DOWN, LEFT, RIGHT, CMD_END
}MOVE_CMD;

同样地,也可以定义一个函数指针数组

const Move move_funcs[] = 
{#define DEF(a,b)  b,CMD_FUNC#undef DEF
};
//编译之后
const Move move_funcs[] = 
{up_func,down_func,left_func,right_func
};

这样就通过预编译阶段做好了索引与回调函数的对应工作,在编译时会直接生成,后面就可以通过索引进行操作了,如

void function(MOVE_CMD mc)
{    if(mc>=CMD_END||p==NULL)return;move_funcs[mc]();
}

工程一般过程:
#define DISPATCH(fn, name, fun, param) fn(name, fun, param)
它接受四个参数,但本质上是将后三个参数(name, fun, param)传递给第一个参数(fn)所代表的宏或函数
#defineENUM_CONSTRUCT(name, fun, param) name,
当被DISPATCH调用时,fn就是这个宏,它会为列表中的每一项生成一个枚举值,后面加一个逗号,从而组合成一个完整的枚举定义
#define IOV_ITEM_STRUCT_CONSTRUCT(name, fun, _param) \
{ \
.update_fn = fun, \
.param = (int)(_param), \
},
专门用于初始化结构体数组元素的“片段”。
#define ENUM_DEF(type) \
typedef enum { MY##type(ENUM_CONSTRUCT)  MY##type##_MAX } my##type##_e;
自动生成一个枚举类型​​
#define STRUCT_DEF(type, name) \
static item_t name##_items[] = { fun##type(STRUCT_CONSTRUCT) };
​​自动生成一个静态的结构体数组​​。

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

相关文章:

  • JS循环机制
  • IS-IS的原理
  • Java超卖问题
  • MySQL安装与使用指南
  • 【读论文】量子关联增强双梳光谱技术
  • 力扣404 代码随想录Day15 第三题
  • 故障排查指南:理解与解决 “No route to host“ 错误
  • NOSQL——Redis
  • MySQL基础知识保姆级教程(四)视图与约束
  • 浅谈中断控制器:从 IRQ 到 IRR、IMR、In-Service Register
  • 软考-操作系统-错题收集(3)文件系统的索引节点结构
  • 【前端】《手把手带你入门前端》前端的一整套从开发到打包流程, 这篇文章都会教会你;什么是vue,Ajax,Nginx,前端三大件?
  • ComPE for win 纯净的PE系统
  • 软考中级数据库系统工程师学习专篇(67、数据库恢复)
  • Spring Security 深度学习(四): 会话管理与CSRF防护
  • 2025 数字化转型期,值得关注的 10 项高价值证书解析
  • Linux笔记---计算机网络概述
  • 视频动作识别模型-C3D
  • 线程池项目代码细节5(解决linux死锁问题)
  • 关系型数据库——GaussDB的简单学习
  • 《投资-43》- 自然=》生物=》人类社会=》商业=》金融=》股市=》投资的共同逻辑:生存竞争与进化论
  • 前端实现查询数据【导出】功能
  • 自制扫地机器人(二) Arduino 机器人避障设计——东方仙盟
  • A股大盘数据-20250901 分析
  • 设计模式:代理模式(Proxy Pattern)
  • HOW - 前端团队组长提升(沟通篇)
  • kubectl-etcd
  • RSA的CTF题目环境和做题复现第1集
  • nacos微服务介绍及环境搭建
  • linux 函数 kthread_should_stop