我刚刚阅读了this关于未定义行为和序列点的SO C ++ FAQ,并进行了一些实验。在下面的代码中,gcc-4.5.2
仅在代码注释中提到的行中给出了警告,尽管之前的一行也显示了未定义的行为,不是吗?你不能说首先执行哪个加法操作数(因为+
不是序列点)。为什么gcc也没有在这一行给我一个警告?
int i=0;
int j=0;
int foo(void) {
i=1;
return i;
}
int main(void) {
i = i + foo();
j = j + (j=1); //Here is a rightly warning
return 0;
}
感谢您的帮助。
答案 0 :(得分:16)
i = i + foo()的行为;未指定但未定义。未定义意味着允许任何可能的行为,甚至中止程序。未指定意味着首先评估i,或者foo()。是的,foo写到同一个i,但由于它发生在一个单独的语句中,所以在该商店之前和之后都有一个序列点。
答案 1 :(得分:1)
程序中的行i = i + foo();
未指定但未定义。
编译器尝试发出没有误报的警告(每次编译器发出警告时,程序员都应该修复缺陷),或者至少具有非常低的误报率。这意味着作为交换,他们有相当多的漏报。为了遵循相同的理念,编译器通常不会对未指明的行为发出警告。
要获得有关您的程序的警告,您应该研究静态分析器,这些分析器对警告更具攻击性,但代价是误报率稍高。静态分析仪可以很好地决定警告未指明的行为。他们中的一些人甚至警告定义的行为虽然被定义,但表明程序员可能很困惑。
答案 2 :(得分:-6)
人类可以看到调用foo()会改变我,但对于计算机程序来说,很难看到。它只是不是为了看到这个而设计的。