我的分号怎么了?(gcc预处理器)

我的分号怎么了?(gcc预处理器),c,gcc,clang,preprocessor,C,Gcc,Clang,Preprocessor,我想我会很聪明,写一个关于禁用/启用中断的小预处理器包装,如下所示: #define WITH_INTERRUPTS_DISABLED(_body) \ do { \ uint32_t primask = DisableGlobalIRQ();

我想我会很聪明,写一个关于禁用/启用中断的小预处理器包装,如下所示:

#define WITH_INTERRUPTS_DISABLED(_body)                                        \
  do {                                                                         \
    uint32_t primask = DisableGlobalIRQ();                                     \
    do {                                                                       \
      _body                                                                    \
    } while (0);                                                               \
    EnableGlobalIRQ(primask);                                                  \
  } while (0)
GCC预处理器与此源一起提供时:

WITH_INTERRUPTS_DISABLED(
  i += 2; 
  quux();
);
。。。生成此输出(为可读性重新格式化):

根据,所有GCC变体的行为如上所述,省略了结束分号。同时,所有
clang
变体的输出都包含分号


有没有办法说服GCC包含分号?

分号没有发生任何变化,GCC生成的分号很好。如果GCC和clang在这个基本问题上有所不同,那将是非常令人震惊的,这肯定是由C标准定义的,并且在实际代码中被广泛使用

不过,Godbolt编译器资源管理器的默认设置会将其过滤掉,可能是因为它看起来像汇编语言中的注释。interjay的示例:

如果关闭“Filter:Comments”,您将看到分号在那里,前面有两行空行:

正如interjay所指出的,浏览器设计用于显示程序集输出,而不是预处理的C,因此,
-E
是这样就不足为奇了

Pc>似乎CLAN省略了空白行,我猜这正好阻止了GooButt认为它是一个注释:

  do { uint32_t primask = DisableGlobalIRQ(); do { i += 2; quux(); } while (0); EnableGlobalIRQ(primask); } while (0);

我认为这种差异没有任何合规性问题,因为在这两种情况下令牌的顺序是相同的。

您的godbolt链接不包含代码;你需要使用共享按钮来获得一个永久链接。实际的godbolt链接:一个关于支持-E输出的godbolt公开问题。你为什么把它变成一个社区wiki?在这种情况下,我看不出有什么理由这么做。@cigien:interjay的评论中有几点很重要,所以我觉得我不应该为此赢得声誉。这是我使用的其他一些SE站点上的常见做法,可能不在这里?耸耸肩。这很好,所以:)肯定更倾向于将有帮助的评论归因于此,但你已经这么做了。你可以直接链接到评论以及你答案中interjay的个人资料(这是我的偏好)。
  do { uint32_t primask = DisableGlobalIRQ(); do { i += 2; quux(); } while (0); EnableGlobalIRQ(primask); } while (0)


   ;
  do { uint32_t primask = DisableGlobalIRQ(); do { i += 2; quux(); } while (0); EnableGlobalIRQ(primask); } while (0);