双字符串化技巧到底是如何工作的?

发布于 2024-09-28 14:50:03 字数 492 浏览 0 评论 0原文

至少有一些 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

揽月 2024-10-05 14:50:03

是的,这是有保证的。

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

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:

... 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".

看春风乍起 2024-10-05 14:50:03

正如 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文