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

时间:2018-09-05 18:34:41

标签: c++ c-preprocessor language-lawyer

我刚才回答了一个有关附加到C宏的问题 在Can I append to a preprocessor macro?

正如答案所说,以下内容在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 ++不同,我会对C和C ++都感兴趣(主要是对 最新版本,在撰写本文时为C18和C ++ 17)

1 个答案:

答案 0 :(得分:2)

  

根据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]

来自gccMSVC的这些pragams的文档似乎都没有非常详尽。因此,他们提供的指导方式不多。