1. 宏定义概述
宏定义是 C 语言预处理指令中最常用的一种,它是一种非常重要的预处理功能。通过宏定义,我们可以将一个标识符定义为一个常量或一个表达式,然后在程序中就可以直接使用这个宏定义来代替该常量或表达式。宏定义可以简化程序的编写,提高程序的可读性。
2. 宏定义语法
宏定义的语法如下:
#define 宏名 宏体
其中,宏名是宏定义的名称,宏体是宏定义的具体内容。宏定义的名称必须遵循 C 语言标识符的命名规则,宏体的具体内容可以是常量、表达式、函数调用等。
3. 宏定义的妙用
在程序中使用宏定义的方法非常简单,只需要直接使用宏定义的名称即可。宏定义的名称就像一个普通的 C 语言标识符一样,可以在程序中任何地方使用。需要提醒的是,宏定义的名称不能作为变量来使用,也不能作为函数的参数或返回值来使用。
4. 宏定义的注意事项
#define DAP_MODULES { \
DAP_MODULE(MODULE_FIRST, "scheduler", \
scheduler_init, scheduler_term), \
DAP_MODULE(MODULE_CONF, "config file", \
cfgfile_init, cfgfile_term), \
DAP_MODULE(MODULE_DPDK, "dpdk", \
dpdk_init, NULL), \
DAP_MODULE(MODULE_GLOBAL_DATA, "global data", \
global_data_init, global_data_term), \
DAP_MODULE(MODULE_MBUF, "mbuf", \
mbuf_init, NULL), \
DAP_MODULE(MODULE_TIMER, "timer", \
timer_init, timer_term), \
DAP_MODULE(MODULE_NETIF, "netif", \
netif_init, netif_term), \
DAP_MODULE(MODULE_CTRL, "ctrl", \
ctrl_init, ctrl_term), \
DAP_MODULE(MODULE_MSG, "msg_sockopt", \
msg_sockopt_init, msg_sockopt_term), \
DAP_MODULE(MODULE_NETIF_CTRL, "netif ctrl", \
netif_ctrl_init, netif_ctrl_term), \
DAP_MODULE(MODULE_INET, "inet", \
inet_init, inet_term), \
DAP_MODULE(MODULE_PDUMP, "pdump", \
pdump_init, pdump_term), \
DAP_MODULE(MODULE_SESS, "session", \
session_init, session_term), \
DAP_MODULE(MODULE_EVENT, "event", \
event_init, event_term), \
DAP_MODULE(MODULE_SHM, "shm", \
shm_init, shm_term), \
DAP_MODULE(MODULE_LAST, "last", \
NULL, NULL) \
}
#define DAP_MODULE(a, b, c, d) a
enum dap_modules DAP_MODULES; //
#undef DAP_MODULE
#define DAP_MODULE(a, b, c, d) b
static const char *dap_modules[] = DAP_MODULES;
#undef DAP_MODULE
typedef int (*module_init_pt)(void);
typedef int (*module_term_pt)(void);
#define DAP_MODULE(a, b, c, d) c
module_init_pt dap_module_inits[] = DAP_MODULES;
#undef DAP_MODULE
#define DAP_MODULE(a, b, c, d) d
module_term_pt dap_module_terms[] = DAP_MODULES;
这段代码定义了一个宏 DAP_MODULE,它接受四个参数,其中第一个参数 a 会被替换为后面的参数。
具体来说,这个宏的作用是将传入的参数 a 赋值给变量 DAP_MODULES。在宏展开的过程中,DAP_MODULE(a, b, c, d) 会被展开成 a,然后将 a 的值赋给 DAP_MODULES。
接下来,代码中定义了一个枚举类型 dap_modules,并将其命名为 DAP_MODULES。这个枚举类型用于表示不同的模块名称。
最后,代码使用 #undef DAP_MODULE 取消了前面定义的宏 DAP_MODULE,以避免后续代码中的命名冲突。
下面是宏展开的结果:
#define DAP_MODULE(a, b, c, d) a
// 定义一个枚举类型 dap_modules
enum dap_modules {
// 枚举项1
DAP_MODULE(MODULE_FIRST, "scheduler", scheduler_init, scheduler_term),
// 枚举项2
DAP_MODULE(MODULE_CONF, "config file", cfgfile_init, cfgfile_term),
// 枚举项3
DAP_MODULE(MODULE_DPDK, "dpdk", dpdk_init, NULL),
// 枚举项4
DAP_MODULE(MODULE_GLOBAL_DATA, "global data", global_data_init, global_data_term),
// 枚举项5
DAP_MODULE(MODULE_MBUF, "mbuf", mbuf_init, NULL),
// 枚举项6
DAP_MODULE(MODULE_TIMER, "timer", timer_init, timer_term),
// 枚举项7
DAP_MODULE(MODULE_NETIF, "netif", netif_init, netif_term),
// 枚举项8
DAP_MODULE(MODULE_CTRL, "ctrl", ctrl_init, ctrl_term),
// 枚举项9
DAP_MODULE(MODULE_MSG, "msg_sockopt", msg_sockopt_init, msg_sockopt_term),
// 枚举项10
DAP_MODULE(MODULE_NETIF_CTRL, "netif ctrl", netif_ctrl_init, netif_ctrl_term),
// 枚举项11
DAP_MODULE(MODULE_INET, "inet", inet_init, inet_term),
// 枚举项12
DAP_MODULE(MODULE_PDUMP, "pdump", pdump_init, pdump_term),
// 枚举项13
DAP_MODULE(MODULE_SESS, "session", session_init, session_term),
// 枚举项14
DAP_MODULE(MODULE_EVENT, "event", event_init, event_term),
// 枚举项15
DAP_MODULE(MODULE_SHM, "shm", shm_init, shm_term),
// 枚举项16
DAP_MODULE(MODULE_LAST, "last", NULL, NULL)
};
// 将枚举类型转换为字符串数组
static const char *dap_modules[] = {
"scheduler",
"config file",
"dpdk",
"global data",
"mbuf",
"timer",
"netif",
"ctrl",
"msg_sockopt",
"netif ctrl",
"inet",
"pdump",
"session",
"event",
"shm",
"last"
};
// 将枚举类型转换为函数指针数组
module_init_pt dap_module_inits[] = {
dpdk_init,
cfgfile_init,
dpdk_init,
global_data_init,
mbuf_init,
timer_init,
netif_init,
ctrl_init,
msg_sockopt_init,
netif_ctrl_init,
inet_init,
pdump_init,
session_init,
event_init,
shm_init,
NULL
};
// 将枚举类型转换为函数指针数组
module_term_pt dap_module_terms[] = {
dpdk_term,
cfgfile_term,
dpdk_term,
global_data_term,
mbuf_term,
timer_term,
netif_term,
ctrl_term,
msg_sockopt_term,
netif_ctrl_term,
inet_term,
pdump_term,
session_term,
event_term,
shm_term,
NULL
};