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
$ 

質問:なぜこれが起こるのですか? 変数が警告を抑制する理由はありますか? constGCCとClangの両方が同意する場合、何かを学ぶ必要がある可能性が高いと思われるため、バグレポートを投げることをためらっています:)

編集:コンパイラの定数の折りたたみが関係している可能性がありますが、動作を説明するには不十分です。最初の例 ( なしconst) では、コンパイラは値を認識しており、値が変更されないことを認識しています。アセンブラーの出力を確認したところ、コンパイラーは定数の折りたたみを行いますが、おそらく式を見て、それが符号なしの型であることを知っているときに変数を既知の定数に置き換えるに、警告が生成されます。つまり、追加するとこの動作が変わるのはなぜですか? 最初の例で警告が出た場合、2 番目の例でも警告を出すことができるはずだと思います。( n < 0 )nconst

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 に答える