这个双线戏法到底是怎么做到的呢?

至少有一些 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 定义?

20770 次浏览

Yes, it's guaranteed.

It works because arguments to macros are themselves macro-expanded, except where the macro argument name appears in the macro body with the stringifier # or the token-paster ##.

6.10.3.1/1:

... After the arguments for the invocation of a function-like macro have been identified, argument substitution takes place. A parameter in the replacement list, unless preceded by a # or ## preprocessing token or followed by a ## preprocessing token (see below), is replaced by the corresponding argument after all macros contained therein have been expanded...

So, if you do STR1(THE_ANSWER) then you get "THE_ANSWER", because the argument of STR1 is not macro-expanded. However, the argument of STR2 is macro-expanded when it's substituted into the definition of STR2, which therefore gives STR1 an argument of 42, with the result of "42".

As Steve notes, this is guarenteed, and it has been guarenteed since the C89 standard -- that was the standard the codified the # and ## operators in macros and mandates recursively expanding macros in args before substituting them into the body if and only if the body does not apply a # or ## to the argument. C99 is unchanged from C89 in this respect.