87

至少有一些C预处理器允许您将宏的值而不是其名称字符串化,方法是将它通过一个类似函数的宏传递给另一个对其进行字符串化的宏:

#define STR1(x) #x
#define STR2(x) STR1(x)
#define THE_ANSWER 42
#define THE_ANSWER_STR STR2(THE_ANSWER) /* "42" */

示例用例在这里

这确实有效,至少在 GCC 和 Clang 中(都带有-std=c99),但我不确定它在 C 标准术语中是如何工作的。

这种行为是否由 C99 保证?
如果有,C99如何保证?
如果不是,那么行为在什么时候从 C 定义变为 GCC 定义?

4

2 回答 2

81

是的,这是有保证的。

它之所以有效,是因为宏的参数本身是宏扩展的,除非宏参数名称出现在带有字符串化符 # 或标记粘贴器 ## 的宏主体中。

6.10.3.1/1:

...在确定了调用类函数宏的参数后,将进行参数替换。替换列表中的参数,除非前面有 # 或 ## 预处理标记或后跟 ## 预处理标记(见下文),在其中包含的所有宏都已展开后,将替换为相应的参数......

所以,如果你这样做STR1(THE_ANSWER),你会得到“THE_ANSWER”,因为 STR1 的参数不是宏扩展的。但是,STR2 的参数在代入 STR2 的定义时宏扩展,因此给 STR1 的参数为42,结果为“42”。

于 2010-05-01T23:24:25.180 回答
21

正如史蒂夫指出的那样,这是有保证的,并且自 C89 标准以来就一直有保证——这是将###运算符编入宏中的标准,并要求在将宏替换为主体之前递归扩展 args 中的宏,当且仅当正文不会将###应用于参数。在这方面,C99 与 C89 没有变化。

于 2010-05-01T23:47:36.793 回答