如何通过宏定义实现C语言枚举的可配置前缀命名?
C语言宏定义前缀控制问题
问题描述
我手头有一个包含数百个如下格式的宏定义库:
#define EVENT_A 0 #define EVENT_B 1 #define EVENT_C 2 ...
为了方便修改EVENT_前缀,我尝试用嵌套宏优化事件定义:
#define DEFINE_EVENT(name,value) EVENT_##name = value DEFINE_EVENT(A, 0) DEFINE_EVENT(B, 1) DEFINE_EVENT(C, 2)
但我希望用宏来控制这个前缀,方便后续处理事件宏的字符串化版本,尝试的写法却无法生效:
#define EVENT_PREFIX "EVENT_" #define DEFINE_EVENT(name,value) EVENT_PREFIX##name = value DEFINE_EVENT(A, 0) DEFINE_EVENT(B, 1) DEFINE_EVENT(C, 2)
之后我改用枚举的方式定义事件:
#define DEFINE_EVENT(name, value) EVENT_##name = value, enum { #include "events.txt" }; #undef DEFINE_EVENT
其中events.txt内容为:
DEFINE_EVENT(A,0) DEFINE_EVENT(B,1) DEFINE_EVENT(C,2)
现在想添加EVENT_PREFIX宏来实现前缀控制,请问下面的写法可行吗?
#define EVENT_PREFIX "EVENT_" #define DEFINE_EVENT(name, value) EVENT_PREFIX##name = value, enum { #include "events.txt" }; #undef DEFINE_EVENT
解答
为什么原写法不可行
你写的EVENT_PREFIX带了双引号,这属于字符串字面量,而宏拼接操作##的作用是将两个**标识符(符合C命名规则的变量、枚举名等)**拼接成一个新的标识符,不能把字符串和标识符拼接成合法的C标识符,所以这种写法完全行不通。
正确的实现方式
要实现前缀的宏控制,需要注意两点:
EVENT_PREFIX必须定义为不带引号的标识符前缀,而非字符串;- 由于宏拼接
##会阻止左侧宏的展开,需要增加一层中间宏来先展开前缀,再完成拼接。
完整代码示例:
// 定义不带引号的前缀宏,直接写标识符前缀 #define EVENT_PREFIX EVENT_ // 中间宏:先展开EVENT_PREFIX,再和name拼接 #define CONCAT_EVENT_NAME(name) EVENT_PREFIX##name // 最终的事件定义宏 #define DEFINE_EVENT(name, value) CONCAT_EVENT_NAME(name) = value, enum { #include "events.txt" }; #undef DEFINE_EVENT
额外:事件宏的字符串化处理
如果需要把枚举名转成对应的字符串(比如把EVENT_A转成"EVENT_A"),可以再添加字符串化的宏:
#define STRINGIFY(x) #x // 将事件名转成字符串 #define EVENT_NAME_TO_STR(name) STRINGIFY(CONCAT_EVENT_NAME(name)) // 使用示例:EVENT_NAME_TO_STR(A) 会被预处理器展开为 "EVENT_A"
内容的提问来源于stack exchange,提问作者Kron
相关产品推荐
相关产品推荐

