【问题标题】:What happened to my semicolon? (gcc preprocessor)我的分号怎么了? (gcc 预处理器)
【发布时间】:2021-07-20 07:20:07
【问题描述】:

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

#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();
);

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

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

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

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

【问题讨论】:

  • 你的godbolt链接不包含代码;你需要使用分享按钮来获得一个永久链接。
  • 实际神螺栓链接:godbolt.org/z/94e4q3ehK
  • Here's 一个关于支持 -E 输出的开放问题。

标签: c gcc clang preprocessor


【解决方案1】:

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

但是,Godbolt 编译器资源管理器的默认设置会将其过滤掉,可能是因为它看起来像汇编语言中的注释。来自 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)


   ;

正如 interjay 指出的那样,Explorer 旨在显示汇编输出,而不是预处理的 C,因此 -Enot supported very well 也就不足为奇了。

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

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

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

【讨论】:

  • 你为什么把它做成一个社区维基?在这种情况下,我看不出有任何理由这样做。
  • @cigien:有几个要点来自 interjay 的 cmets,所以我觉得我不应该为此赢得声誉。这是我使用的其他一些 SE 网站上的常见做法,也许不在这里?耸耸肩。
  • 在 SO 上完全没问题 :) 最好将帮助的 cmets 归于属性,但您已经这样做了。您可以在答案中直接链接到 cmets 以及 interjay 的个人资料(这是我的偏好)。
猜你喜欢
  • 1970-01-01
  • 2019-02-02
  • 1970-01-01
  • 2014-09-13
  • 2011-04-24
  • 2023-03-21
  • 2017-07-18
  • 2014-06-14
  • 2021-11-27
相关资源
最近更新 更多