双串化技巧究竟如何工作?
至less有一些C预处理器允许你通过将一个类似macros的macros传递给另一个对其进行string化的macros来对其进行string化,而不是通过它的名称:
#define STR1(x) #x #define STR2(x) STR1(x) #define THE_ANSWER 42 #define THE_ANSWER_STR STR2(THE_ANSWER) /* "42" */
这里的例子用例。
这是行不通的,至less在GCC和Clang(都是-std=c99
),但我不确定它是如何在C标准方面的工作。
这种行为是否由C99保证?
如果是这样,C99如何保证它?
如果不是,行为从C定义到GCC定义的哪一点?
是的,这是保证。
它的工作原理是因为macros的参数本身是macros扩展的, 除非macros参数名用string#或者标记 – 贴子##出现在macros体中。
6.10.3.1/1:
…在调用类似函数macros的参数被识别之后,参数replace发生。 replace列表中的参数(除非前面有#或##预处理标记或后面跟着一个##预处理标记(请参见下面的内容))在其中包含的所有macros已被展开之后由相应的参数replace…
所以,如果你做STR1(THE_ANSWER)
那么你会得到“THE_ANSWER”,因为STR1的参数不是macros扩展的。 然而,当STR2 被 STR2定义代入时,STR2的论点被macros观扩充,因此STR1的论点为42
,结果为“42”。
正如史蒂夫所指出的那样,这是有保证的,而且自从C89标准以来,它已经得到了保证 – 这是macros和macros中的#和##运算符编码的标准,在将它们代入到体内之前recursion地扩展macros,当且仅当身体不会将#或##应用于参数。 C99在这方面与C89没有任何变化。