【c语言】:X宏的应用

本文介绍了如何使用X宏来简化枚举类型与相关字符串的关联,通过示例展示了在故障类型和数据帧格式定义中,如何利用X宏减少重复修改和出错可能性。X宏的使用使得在一处定义即可同步更新相关联的枚举和数组,提高了代码的维护性和一致性。
摘要由CSDN通过智能技术生成

在项目中有时会遇到这样的情况:枚举信息需要关联相关的信息。

比如,定义一系列的故障类型 , 为了便于故障进行日志输出 , 一般会定义一个与之关联的字符串数组。

 typedef enum
 {
     PARAM_ERR,
     PARSER_ERR,
     TIMEOUT_ERR,
     NOTEXIT_ERR,
     ...
 }SYS_ERR_t;
 ​
 const char* ERR_INFO[]=
 {
     "param error",
     "parser error",
     "timeout error",
     "not exit error"
 };
 #define ERR_STR(x)   ERR_INFO[x]
 ​
 void test(void)
 {
     printf(ERR_STR(PARAM_ERR));
     printf(ERR_STR(NOTEXIT_ERR));
 }

目前这种定义方法 ,枚举和字符串需要同时修改 ,有可能造成只增加枚举而导致数组越界

使用X宏

 #define  ERR_T     \
             X(PARAM_ERR , "param error")\
             X(PARSER_ERR , "parser error")\
             X(TIMEOUT_ERR , "timeout error")\
             X(NOTEXIT_ERR , "not exit error")
 ​
 #define X(a , b)     a,
 typedef enum
 {
     ERR_T
 }SYS_ERR_t;
 #undef  X
 ​
 #define X(a , b)  b,
 const char* ERR_INFO[]=
 {
     ERR_T
 };

使用X宏最终只需要 修改 ERR_T 即可 ,减少出错的可能性 ,至于为啥叫X 宏 , 没有找到相关说明,本质是使用了#undef 对 X进行了取消定义,进行重定义 , 导致 枚举 和数组 使用相同的 ERR_T 但 表示的内容不同 ,这里很好的说明了预处理阶段 只是 一个替换过程 ,程序 预处理完成后 ,所有的宏都不将存在,而是替换成了对应的文本。

 

另一个实用的例子 :

定义一种数据帧格式 , 功能码 加有效字段 ,不同功能码长度不同 ,附带不同信息

typedef struct
 {
     uint8_t cmd;
     uint8_t len;
     const char* info
 }p_cmd_t;
 ​
 enum
 {
     LAP_CMDUL_CFRM          = 0x00,
     LAP_CMDUL_PPAT          = 0x02,
     LAP_CMDUL_TEMP          = 0x10,
     LAP_CMDUL_ALERT         = 0x0F,
     LAP_CMDUL_TOTAL_FLOW    = 0x71,
     LAP_CMDUL_RATE_FLOW     = 0x72,
     LAP_CMDUL_REVERSE_FLOW  = 0x73,
     LAP_CMDUL_FROZEN_FLOW   = 0x74,
     LAP_CMDUL_VER           = 0x90,
     LAP_CMDUL_TIMEUL        = 0x98,
 };
 ​
 p_cmd_t  cmd_tab[]=
 {
     {LAP_CMDUL_CFRM          ,  1 ,  "LAP_CMDUL_CFRM"        }, 
     {LAP_CMDUL_PPAT          ,  2 ,  "LAP_CMDUL_PPAT"        },
     {LAP_CMDUL_TEMP          ,  3 ,  "LAP_CMDUL_TEMP"        },
     {LAP_CMDUL_ALERT         ,  4 ,  "LAP_CMDUL_ALERT"       },
     {LAP_CMDUL_TOTAL_FLOW    ,  5 ,  "LAP_CMDUL_TOTAL_FLOW"  },
     {LAP_CMDUL_RATE_FLOW     ,  6 ,  "LAP_CMDUL_RATE_FLOW"   },
     {LAP_CMDUL_REVERSE_FLOW  ,  7 ,  "LAP_CMDUL_REVERSE_FLOW"},
     {LAP_CMDUL_FROZEN_FLOW   ,  8 ,  "LAP_CMDUL_FROZEN_FLOW" },
     {LAP_CMDUL_VER           ,  9 ,  "LAP_CMDUL_VER"         }, 
     {LAP_CMDUL_TIMEUL        ,  9 ,  "LAP_CMDUL_TIMEUL"      },
 };

X宏的实现方法

#define   CMD_LIST   \
         X(LAP_CMDUL_CFRM        , 0x00  , 1  , "LAP_CMDUL_CFRM")\
         X(LAP_CMDUL_PPAT        , 0x02  , 2  , "LAP_CMDUL_PPAT")\
         X(LAP_CMDUL_TEMP        , 0x10  , 3  , "LAP_CMDUL_TEMP")\
         X(LAP_CMDUL_ALERT       , 0x0F  , 4  , "LAP_CMDUL_ALERT")\
         X(LAP_CMDUL_TOTAL_FLOW  , 0x71  , 5  , "LAP_CMDUL_TOTAL_FLOW")\
         X(LAP_CMDUL_REVERSE_FLOW, 0x72  , 6  , "LAP_CMDUL_REVERSE_FLOW")\
         X(LAP_CMDUL_FROZEN_FLOW , 0x73  , 7  , "LAP_CMDUL_FROZEN_FLOW")\
         X(LAP_CMDUL_VER         , 0x90  , 8  , "LAP_CMDUL_VER")\
         X(LAP_CMDUL_TIMEUL      , 0x98  , 9  , "LAP_CMDUL_TIMEUL")\
 ​
 /*以下内容无需再修改*/
 #define X(a ,b , c ,d)     a = b,
 enum
 {
     CMD_LIST
 };
 #undef X
 ​
 #define  X(a , b ,c ,d)   {b,c,d},
 p_cmd_t  cmd_tab[]= 
 {
     CMD_LIST
 };
 #undef X

总体来看 ,只是将分散的修改集中到了一起 ,修改的时候方便,不会出错。而且可以将CMD_LIST 任意成员进行关联 ,只需要重定义X 即可。可能两个事务的关联还难以体现X宏的 作用 , 当多个定义都有关联时 , 修改一个需要同步修改其他的 , 这个时候才能体现X宏的作用。

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值