为什么GCC在这个例子中没有发出警告

时间:2017-05-14 11:06:33

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

启用-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]

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

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

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

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

1 个答案:

答案 0 :(得分:6)

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

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

为了使gcc代码分析能够发现此错误,编译器必须在整个生命周期内跟踪*a的内容。虽然在您的示例中看起来很简单,但是更复杂的程序,例如,数据从用户输入读入a,会导致无法进行此类分析。