C语言中的X-MACRO技巧

wuchangjian2021-11-28 09:30:27编程学习

X-Macro只是一种宏的使用技巧,并不是什么特殊的语法,但却在实际应用中十分高效简洁,且拓展性非常强;

首先我们介绍一下#define#undef的用法:

#define X_MACRO(a, b)	a
#undef X_MACRO
#define X_MACRO(a, b)	b
#undef X_MACRO

示例:

#define X_MACRO(a, b)	a
int x = X_MACRO(10, 100)
#undef X_MACRO
    
#define X_MACRO(a, b)	b
int y = X_MACRO(10, 100)
#undef X_MACRO

#undef可以取消定义宏,然后再通过#define重新定义宏,此时得到的xy的值分别是10100


X-Macro其实就是通过#define#undef实现的一种宏定义的技巧;

首先我们可以定义出这样的宏列表:

#define MACROS_TABLE                    \
    X_MACROS(CMD_LED_ON,  led_on)       \
    X_MACROS(CMD_LED_OFF, led_off)      \

当我们需要一个命令列表时可以这样定义:

typedef enum
{
    #define X_MACROS(a, b) a,
    MACROS_TABLE
    #undef X_MACROS
    CMD_MAX
}cmd_e;

宏展开后是这样的形式:

typedef enum
{
    CMD_LED_ON,
    CMD_LED_OFF,
    CMD_MAX
}cmd_e;

如果我们需要一个命令的字符串列表用作log打印时也可以定义这样的列表:

const char* cmd_str[] = 
{
    #define X_MACROS(a, b) #a,
    MACROS_TABLE
    #undef X_MACROS
};

宏展开后是这样的形式:

const func func_table[] = 
{
    “CMD_LED_ON”,
    “CMD_LED_OFF”,
};

当我们需要一个函数列表时可以这样操作:

const func func_table[] = 
{
    #define X_MACROS(a, b) b,
    MACROS_TABLE
    #undef X_MACROS
};

宏展开后是这样的形式:

const func func_table[] = 
{
    led_on,
    led_off,
};

由于函数列表与命令列表都是根据MACROS_TABLE这个宏拓展出来的,是一一对应的,所以我们可以直接使用索引的方式来调用函数:

static void cmd_handle(cmd_e cmd)
{
    if(cmd < CMD_MAX)
    {
        func_table[cmd]((void*)cmd_str[cmd]);
    }
}

使用X-MACRO对于此类的命令消息处理十分高效简洁,非常实用,且拓展性非常强。


整体代码如下:

#include <stdio.h>

#define MACROS_TABLE                    \
    X_MACROS(CMD_LED_ON,  led_on)       \
    X_MACROS(CMD_LED_OFF, led_off)      \

/*定义命令列表*/
typedef enum
{
    #define X_MACROS(a, b) a,
    MACROS_TABLE
    #undef X_MACROS
    CMD_MAX
}cmd_e;


/*定义字符串列表用作Log打印*/
const char* cmd_str[] = 
{
    #define X_MACROS(a, b) #a,
    MACROS_TABLE
    #undef X_MACROS
};


typedef void (*func)(void* p);

static void led_on(void* p)
{
    printf("%s \r\n", (char *)p);
}

static void led_off(void* p)
{
    printf("%s \r\n", (char *)p);
}

/*定义函数列表*/
const func func_table[] = 
{
    #define X_MACROS(a, b) b,
    MACROS_TABLE
    #undef X_MACROS
};


/*直接通过索引的方式调用函数*/
static void cmd_handle(cmd_e cmd)
{
    if(cmd < CMD_MAX)
    {
        func_table[cmd]((void*)cmd_str[cmd]);
    }
}


void main(void)
{
    cmd_handle(CMD_LED_ON);
    cmd_handle(CMD_LED_OFF);
}

相关文章

web前端制作一个简易的小网页-主页搜索框

 效果图:   附上原图  代码: <...

【JAVA基础】06JAVA中的this

当形参名字等于成员变量名,就会导致调用的时候成员变量名会输出默认值...

实验一 Python 基本操作

实验一 Python 基本操作

input 语句 (1)编程程序,输入...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。