【问题标题】:Why doesn't GCC throw a warning in this example为什么 GCC 在这个例子中不抛出警告
【发布时间】:2017-10-13 06:35:03
【问题描述】:

启用-Wsequence-point 后,当发现未定义的行为代码时,GCC 应该警告用户。例如

b = a + ++a;

应该被 GCC 注意到并且应该被报告为“未定义的行为”代码(因为 ISO C 没有指定评估操作数以进行加法的顺序)。

但是,我使用了语法并尝试了这个:

int *a = malloc(sizeof(int) * 2);
a[0] = 1;
printf("%d\n", *(a + (*a)++ - *a));

当然,我收到了警告

警告:'*a' 上的操作可能未定义 [-Wsequence-point]

这是我的预期,因为在处理第三个操作数时,*a(即a[0])的值可能会增加或可能不会增加。但是,我尝试了以下一个:

int *a = malloc(sizeof(int) * 2);
a[0] = 1;
printf("%d\n", *(a + (*a)++ - 1));

我很惊讶,因为我没有收到任何警告。这不应该也是UB吗?我的意思是,根据 ISO C99,后增量操作可以在表达式评估期间的任何时候进行评估(逗号运算符和三元运算符除外)。在我的后一个示例中,我不是在递增指针,而是递增它指向的整数。所以,根据标准,它可以在任何时候递增(这意味着它可以在计算整个表达式后递增),所以程序可以打印12,对吧?

为什么 GCC 不抛出任何警告?还是我错过了什么?我对规格的理解有误吗?

【问题讨论】:

    标签: c pointers gcc compiler-warnings compiler-optimization


    【解决方案1】:

    gcc 的静态分析工具无法处理这种情况。

    *(a + (*a)++ - x) 表达式对于 gcc 的静态分析来说太难了,因为它在某些非常特殊的情况下由于缺少序列点而导致未定义的行为 - 即当 *a 包含 x 时。这是(*a)++ - x相互“撤消”的时候,所以整体表达就等于*a加上一些副作用。

    为了让 gcc 代码分析发现这个错误,编译器必须在 *a 的整个生命周期内跟踪其内容。尽管在您的示例中看起来很简单,但如果使用更复杂的程序(例如,从用户输入将数据读入 a),则无法进行此类分析。

    【讨论】:

      猜你喜欢
      • 2021-12-27
      • 1970-01-01
      • 2019-03-22
      • 2014-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-05
      • 2014-11-02
      相关资源
      最近更新 更多