2016-04-04 16 views
-3

は、以下のコードを検討:符号なしタイプのアンダーフロー警告が表示されないのはなぜですか?

unsigned int n = 0; 
unsigned int m = n - 1;    // no warning here? 
if (n > -1) { 
    std::cout << "n > -1.\n"; 
} else { 
    std::cout << "yes, 0 is not > -1.\n"; 
} 

上記のコードは、符号付きおよび符号なし整数式を比較するためのif条件if (m > -1)に警告を生成します。私はそれに反対していません。最初の2つの割り当てステートメントは私を悩ますものです。

unsigned int n = 0; 
unsigned int m = n - 1; 

私の思考コンパイラから減算する試みがあったこと、それは変数nは、最初の行から0の値を符号なしであることを知っているので、私の第二の割り当てに警告を与えられたとしているべきであるということですゼロの値を返し、それを符号なしの型に割り当てます。

2回目の割り当て後の次の行がifの文などと異なる場合は、関係するコードがスリップしている可能性があります。

はい、mへの割り当ての前に狭い変換があります。はい、コンパイラはMarshall ClowのC++ Now 2017 Lightning Talk(Fighting Compiler Warnings)にも言及しています。

short s = 3 * 6; 
short s = integer * integer; 
short s = integer; 

コンパイラは、そのコードでアンダーフローが発生する可能性について教えてくれませんか?

コンパイラ:

  • クラン3.7/4.0(-Wall -Wextra)
  • GCC 5.3/7.1.1(-Wall -Wextra -pedantic)
  • のMicrosoft C/C++ 19.00.23506
+0

どのような警告が表示されますか?あなたがif文で受ける警告は、「符号なしint m = n-1;で起きていないもの」である符号付き整数式と符号なし整数式の比較です* – NathanOliver

+0

'-Wall'オプションと' -Wextra'オプションを試しましたか? GCCの? – Plouff

+0

@Plouff:はい、GCCで-Wall -Wextraを使用しました。 –

答えて

1

if (n > -1)は決して偽になることはありませんが、unsigned int m = n - 1;は本当の法的表現です。 5/9から、署名されていない型に一貫した型を持たせる方法に関するルールがあります。最終的なデフォルト条件を除いてすべてが失敗します。

それ以外の場合、両方のオペランドは符号付き整数 型のオペランドの型に対応する符号なし整数 型。

符号なし演算は、モジュロ演算を使用するために明確に定義されているため、式全体が正当であり、明確に定義されています。彼らはまだ警告を発することに決めたかもしれませんが、あまりにも多くの偽陽性を引き起こすようなトリックを使って十分なレガシーコードが存在するかもしれません。

+0

この種の問題について警告を発する無料の静的コードチェッカーはありますか? – Plouff

+0

"レガシーコード":これはレガシーコードである必要はありません**、それは新しいコードで書くには完全に有効です。一方、bigint型のコード(ラップアラウンドが必要な場所)やビットフィールド以外のものには、符号なしの型を使用するのは、通常は間違っています。 –

関連する問題