至少有一些 C 预处理器允许你将宏的值(而不是它的名称)通过一个类似函数的宏传递给另一个将它串行化的宏来进行字符串化:
#define STR1(x) #x
#define STR2(x) STR1(x)
#define THE_ANSWER 42
#define THE_ANSWER_STR STR2(THE_ANSWER) /* "42" */
示例用例here。
这确实有效,至少在GCC和Clang(都有-std=c99
),但我不确定 它是如何工作的C标准术语。
这种行为是否由C99保证?
如果是这样,C99如何保证呢?
如果不是,那么行为在什么时候从C定义到GCC定义?
答案 0 :(得分:74)
是的,这是有保障的。
它的工作原理是因为宏的参数本身是宏扩展的,除了,其中宏参数名称出现在带有stringifier#或token-paster ##的宏体中。
6.10.3.1/1:
...之后的争论 调用类似函数的宏 已经确定,争论 替代发生。一个参数 在替换列表中,除非 之前是#或##预处理 令牌或后跟## 预处理令牌(见下文),是 由相应的参数替换 在其中包含所有宏之后 已经扩大了...
所以,如果你做STR1(THE_ANSWER)
那么你会得到“THE_ANSWER”,因为STR1的参数不是宏扩展的。但是,当STR2 的参数被替换为STR2的定义时,的参数是宏扩展的,因此STR1的参数为42
,结果为“42”。
答案 1 :(得分:19)
史蒂夫指出,这是保守的,并且自C89标准以来一直保证 - 这是宏中编码#和 ## 运算符的标准并且当且仅当主体不将#或 ## 应用于参数时,才强制在args中将宏替换为args之前的宏。在这方面,C99与C89相同。