如何对C语言宏进行拼接、求值与字符串化?
解决宏拼接后先求值再字符串化的问题
你遇到的核心问题是:#字符串化操作符不会自动展开它参数里的宏——直接用它处理拼接后的宏名(比如FOO_ONE),只会把宏名本身转成字符串,而不是先展开宏的实际值。我们可以通过两层宏嵌套的技巧来解决这个问题。
为什么你的原有写法不行?
你的CONCAT宏直接把拼接后的mac##_ONE传给STRINGIFY,但#FOO_ONE只会将标识符FOO_ONE转换成字符串"FOO_ONE",而不会先展开FOO_ONE对应的宏值12。这就是你得到FOO_ONEFOO_TWO而不是1234的原因。
正确的宏实现
#include <stdio.h> #define FOO_ONE 12 #define FOO_TWO 34 #define BAR_ONE 56 #define BAR_TWO 78 // 基础字符串化宏:直接将参数转为字符串 #define STRINGIFY(x) #x // 关键的中间层:先展开参数,再调用字符串化宏 #define STRINGIFY_EXPANDED(x) STRINGIFY(x) // 拼接宏前缀和后缀,展开为实际值后字符串化,最终自动拼接 #define MAKE_MAC(mac) STRINGIFY_EXPANDED(mac ## _ONE) STRINGIFY_EXPANDED(mac ## _TWO) int main(int argc, char *argv[]) { printf("FOO: " MAKE_MAC(FOO) "\n"); printf("BAR: " MAKE_MAC(BAR) "\n"); return 0; }
工作原理拆解
- 拼接宏名:当调用
MAKE_MAC(FOO)时,mac##_ONE会拼接成FOO_ONE,mac##_TWO拼接成FOO_TWO。 - 触发宏展开:这两个拼接结果传入
STRINGIFY_EXPANDED后,宏展开规则会先将FOO_ONE展开为12,FOO_TWO展开为34。 - 字符串化:展开后的值再传入
STRINGIFY,分别被转成字符串"12"和"34"。 - 自动拼接:C语言中相邻的字符串字面量会自动合并,所以
"12""34"最终变成"1234",完全符合你的期望输出。
补充小知识
宏展开的优先级规则是:如果宏参数不是#或##的操作数,那么在替换到宏体之前会先被展开。STRINGIFY_EXPANDED的作用就是打破直接字符串化的限制,让拼接后的宏名先展开为实际值,再被转成字符串。
内容的提问来源于stack exchange,提问作者ysap
相关产品推荐
相关产品推荐

