关于const抑制的重言式比较的警告?

时间:2013-03-02 10:05:29

标签: c++ gcc warnings clang

以下代码会在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),编译器确实知道该值并且它永远不会更改。我检查了汇编程序输出,编译器确实进行了常量折叠,但是仍然生成警告,可能是之前它在看到表达式{{{}时用已知常量替换变量1}}并且知道( n < 0 )是无符号类型。这就是说:当我添加n时,为什么这种行为会发生变化?我认为如果第一个例子产生警告,也应该可以为第二个例子生成警告。

2 个答案:

答案 0 :(得分:4)

这是一个明确的常量 - 你的意图。您所需的警告有效地从以下地址转移:

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警告,其中值未知。

答案 1 :(得分:2)

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

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

因此,没有警告。