双字符串化技巧到底是如何工作的?
至少有一些 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 定义?
At least some C preprocessors let you stringize the value of a macro, rather than its name, by passing it through one function-like macro to another that stringizes it:
#define STR1(x) #x
#define STR2(x) STR1(x)
#define THE_ANSWER 42
#define THE_ANSWER_STR STR2(THE_ANSWER) /* "42" */
Example use cases here.
This does work, at least in GCC and Clang (both with -std=c99
), but I'm not sure how it works in C-standard terms.
Is this behavior guaranteed by C99?
If so, how does C99 guarantee it?
If not, at what point does the behavior go from C-defined to GCC-defined?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
是的,这是有保证的。
它之所以有效,是因为宏的参数本身是宏扩展的,例外,其中宏参数名称以字符串化器 # 或标记粘贴器 ## 出现在宏主体中。
6.10.3.1/1:
因此,如果执行
STR1(THE_ANSWER)
,则会得到“THE_ANSWER”,因为 STR1 的参数未进行宏展开。但是,当 STR2 的参数代入 STR2 的定义时,它会被宏扩展,因此为 STR1 提供了一个参数42
,结果为“42”。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:
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 of42
, with the result of "42".正如 Steve 所指出的,这是有保证的,而且自 C89 标准以来就一直得到保证——该标准将 # 和 ## 运算符编入宏和递归命令中当且仅当主体未将 # 或 ## 应用于参数时,才在将 args 中的宏替换到主体中之前对其进行扩展。 C99 在这方面与 C89 没有变化。
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.