2017-05-14 103 views
5

如果启用了-Wsequence-point,当未定义的行为代码被发现时,GCC应该警告用户。例如为什么在这个例子中GCC不会发出警告

b = a + ++a; 

应该由海湾合作委员会注意到,应报告为“未定义行为”的代码(因为ISO C没有指定除了评估操作数的顺序)。

不过,我打了语法,我想这一个:

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

当然,我得到了警告

警告:“*”可以未定义[操作 - Wsequence点]

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

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

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

为什么GCC不会发出任何警告?或者我错过了什么?我错误地理解了规格吗?

回答

6

gcc的静态分析工具不能处理这种情况。

表达*(a + (*a)++ - x)太难了,GCC的静态分析,因为这会导致不确定的行为,由于在某些非常特殊的情况下,缺乏序列点 - 即,当*a包含x。这是当(*a)++ - x彼此“撤消”,所以整体表达等于*a加上一些副作用。

为了让海湾合作委员会代码分析发现此错误,编译器必须在其整个生命周期中跟踪*a的内容。虽然在你的例子中它看起来很简单,但是一个更复杂的程序,比如说,从用户输入中将数据读入a,使得这种分析变得不可能。

相关问题