以下代码会在 GCC 和 Clang 上生成警告:
int main() {
unsigned n = 0;
return ( n < 0 ) ? 1 : 0;
}
警告是:
$ g++-4.7 -std=c++11 -O3 -Wall -Wextra t.cc -o t
t.cc: In function ‘int main()’:
t.cc:3:16: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits]
$ clang++-3.2 -std=c++11 -O3 -Wall -Wextra t.cc -o t
t.cc:3:14: warning: comparison of unsigned expression < 0 is always false [-Wtautological-compare]
return ( n < 0 ) ? 1 : 0;
~ ^ ~
1 warning generated.
$
到目前为止,一切都很好。现在我将变量更改为const
:
int main() {
const unsigned n = 0;
return ( n < 0 ) ? 1 : 0;
}
两个编译器都突然很乐意在没有警告的情况下编译代码:
$ g++-4.7 -std=c++11 -O3 -Wall -Wextra t.cc -o t
$ clang++-3.2 -std=c++11 -O3 -Wall -Wextra t.cc -o t
$
问题:为什么会发生这种情况?有没有原因,为什么const
变量会抑制警告?如果 GCC 和 Clang 都同意,我会犹豫是否向他们提交错误报告,因为我似乎更有可能需要学习一些东西 :)
编辑:编译器的不断折叠可能与它有关,但不足以解释行为。在第一个示例中(没有const
),编译器确实知道该值并且它永远不会改变。我检查了汇编程序的输出,编译器确实进行了常量折叠,但它仍然会生成警告,可能是在它看到表达式( n < 0 )
并知道它n
是无符号类型时用已知常量替换变量之前。也就是说:为什么当我添加时这种行为会发生变化const
?我认为如果第一个示例产生警告,那么也应该可以为第二个示例产生警告。