根据 c++ 标准在该宏定义中推送/弹出宏时的行为是什么

What is the behavior when pushing/popping a macro inside that macro definition according to c++ standard

本文关键字:是什么 标准 c++ 宏定义 根据      更新时间:2023-10-16

>我刚才回答了一个关于附加到 C 宏的问题 我可以追加到预处理器宏吗?

正如答案所说,以下内容适用于 clang 和 g++,但在 msvc 中无效

#define pushfoo _Pragma("push_macro("foo")") //for convenience
#define popfoo _Pragma("pop_macro("foo")") //I tried __pragma and __Pragma for msvc as well
#define foo 1
pushfoo                           //push the old value
#undef foo                        //so you don't get a warning on the next line
#define foo popfoo foo , 2        //append to the previous value of foo
pushfoo
#undef foo
#define foo popfoo foo , 3
pushfoo
#undef foo
#define foo popfoo foo , 4

foo //this whole list will expand to something like popfoo foo popfoo foo popfoo foo , 4
//which will in turn expand to 1 , 2 , 3 , 4
foo //the second time this will expand to just 1

虽然这似乎确实有效,但我想知道这是否只是碰巧适用于 gcc 的事情 和 clang,但 msvc 也(或仅(正确,或者他们表现出的行为是强制性行为 按语言规范。我对 C 和 C++ 都感兴趣,如果它们不同(主要对 最新版本,C18 和 C++撰写本文时为 17(

根据 c++ 标准在该宏定义中推送/弹出宏时的行为是什么?

在 C 和 C++ 中,#pragma_Pragma的结果都是实现定义的,因此标准不控制它们的行为。请参阅 C11 6.10.6p1:

表单的预处理指令

# pragma pp-tokensopt new-line

其中预处理令牌STDC不立即遵循指令中的杂注(在任何宏替换之前(174(导致实现以实现定义的方式运行。该行为可能会导致翻译失败,或导致翻译器或生成的程序以不符合的方式运行。任何未被实现识别的此类杂注都将被忽略。

和 6.10.9 涵盖_Pragma.

以及最新的C++草案[cpp.pragma]:

表单的预处理指令

# pragma pp-tokensopt new-line

使实现以实现定义的方式运行。*该行为可能会导致翻译失败,或导致转换器或生成的程序以不符合的方式运行。实现无法识别的任何杂注都将被忽略。

另请参阅 [cpp.pragma.op]

来自 gcc 或 MSVC 的这些 pragams 的文档似乎都不是很详细。因此,他们没有提供太多指导。