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

fea*_*ool 3 c gcc preprocessor clang

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

#define WITH_INTERRUPTS_DISABLED(_body)                                        \
  do {                                                                         \
    uint32_t primask = DisableGlobalIRQ();                                     \
    do {                                                                       \
      _body                                                                    \
    } while (0);                                                               \
    EnableGlobalIRQ(primask);                                                  \
  } while (0)
Run Code Online (Sandbox Code Playgroud)

GCC 预处理器,当出现此源时:

WITH_INTERRUPTS_DISABLED(
  i += 2; 
  quux();
);
Run Code Online (Sandbox Code Playgroud)

...生成此输出(重新格式化以提高可读性):

do {
  uint32_t primask = DisableGlobalIRQ();
  do {
    i += 2;
    quux();
  } while (0);
  EnableGlobalIRQ(primask);
} while (0)
Run Code Online (Sandbox Code Playgroud)

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

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

Nat*_*dge 6

分号没有发生任何变化,GCC 生成它就好了。如果 GCC 和 clang 在这种基本的东西上有所不同,那将是非常令人吃惊的,这肯定必须由 C 标准很好地定义并广泛用于现实世界的代码中。

但是 Godbolt Compiler Explorer 的默认设置会将其过滤掉,可能是因为它看起来像汇编语言中的注释。来自 interjay 的示例:https ://godbolt.org/z/94e4q3ehK

如果您关闭“过滤器:评论”,您将看到分号在那里,前面有几行空行:https : //godbolt.org/z/7n896or8Y

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


   ;
Run Code Online (Sandbox Code Playgroud)

作为interjay指出,在资源管理器的目的是显示组件的输出,没有预处理的C,所以它并不奇怪,-E不支持的非常好

似乎 clang 省略了空行,我猜这恰好是为了防止 Godbolt 认为这是一个评论:

  do { uint32_t primask = DisableGlobalIRQ(); do { i += 2; quux(); } while (0); EnableGlobalIRQ(primask); } while (0);
Run Code Online (Sandbox Code Playgroud)

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

  • @cigien:几个重要的观点来自 interjay 的评论,所以我觉得我不应该因此而赢得声誉。这是我使用的其他一些 SE 网站上的常见做法,也许不是在这里?耸耸肩。 (2认同)