9

以下代码会在 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?我认为如果第一个示例产生警告,那么也应该可以为第二个示例产生警告。

4

2 回答 2

6

这是一个明确的常数——你的意图。您所需的警告有效地从以下位置转移:

warning: comparison of unsigned expression < 0 is always false [-Wtautological-compare]
return ( n < 0 ) ? 1 : 0;
         ~ ^ ~

-Wunreachable-code什么时候const

warning: will never be executed [-Wunreachable-code]
return ( n < 0 ) ? 1 : 0;
                   ^

注意:-Wtautological-compare编译器可能仍会在值未知的情况下发出警告。

于 2013-03-02T10:24:29.270 回答
2

当变量不是const时,它可能会改变,编译器不知道它。这就是为什么会有警告。如果是const,它永远不会改变。这样,编译器可以n用 的实际值替换任何出现的n,在这种情况下:

return ( 0 < 0 ) ? 1 : 0;
-> return 0;

因此,没有警告。

于 2013-03-02T10:09:56.947 回答