【问题标题】:GCC evaluation of compound statement复合语句的 GCC 评估
【发布时间】:2017-02-03 00:10:03
【问题描述】:

我发现了以下构造,其中一个变量被分配给一个似乎是复合语句的东西,foo,在驱动程序中。为了比较,bar 产生未定义的行为,将相同的代码视为正确的函数。它似乎不符合我对 C 语言及其预处理器的理解,所以我怀疑它是 GCC 扩展。这里执行的逻辑是什么? (见输出here。)

#include <stdio.h>

#define foo(c) ({ int x = c; x; })

int bar(char c) {
    int x = c;
    x;
}

int main(void) {
    int x = foo('0');
    int y = bar('A');
    printf("%d\n%d\n", x, y);
    return 0;
}

输出:

48
0

【问题讨论】:

  • 既然你已经怀疑是 gcc 扩展了,为什么在询问之前没有检查文档?你还做了什么来找出答案?
  • @Olaf 我确实尝试了广泛的搜索,但找不到产生结果的关键字。我能够从给定的函数版本中找到我怀疑的 UB 的来源,但这与宏版本不太一样。我浏览了 GCC 手册,但没有找到对其的具体参考,因为有足够多的扩展使线性搜索变得困难。此外,我还亲自咨询了一些不知道这个结构的同事。我相信我进行了足够多的研究来回答这个问题。
  • 不到 5 分钟的搜索导致 gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html#Statement-Exprs 包括术语“声明”和“声明”,这正是您上面所拥有的。当涉及到编程和许多其他领域时,如何正确搜索是一项基本技能。旁注:见How to Ask,你应该在你的问题中表现出你的努力!
  • 现在知道了答案,找到这个是微不足道的。昨天我的搜索能力似乎让我失望了。感谢您的反馈。

标签: c gcc c-preprocessor gcc-statement-expression


【解决方案1】:

这里涉及到两个不同的东西。

首先,所谓的“语句表达式”({ int x = c; x; }),它是 GCC 扩展。 GCC 中的这个表达式的计算结果是明确定义的值x。它计算的值由({...}) 中的最后一个表达式定义,在您的情况下为x。 (顺便说一句,预处理器与它几乎没有关系。您不必涉及预处理器即可在 GCC 中使用语句表达式。)

其次,您的函数bar,它被声明为返回int,但缺少返回语句。这与任何扩展无关。此函数不返回任何定义的值。如果调用代码尝试使用bar 返回的值,则行为未定义。 bar 末尾的 x 表达式只是一个不会改变任何内容的空操作。

【讨论】:

    【解决方案2】:

    它确实是一个 GCC 扩展,在 GCC manual 中有描述。在需要表达式的地方,您可以提供一个用大括号括起来的块作为有效表达式,其值为该块中的最后一个表达式。

    C 不会在函数末尾的表达式语句中自动插入return,因此bar 确实是UB。 GCC 也没有实现任何扩展。但是对于 GCC 扩展,以下内容是合法的:

    int bar(char c) {
      return ({
        int x = c; 
        x; 
      });
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-12-08
      • 2015-04-07
      • 1970-01-01
      • 1970-01-01
      • 2010-10-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多