web-dev-qa-db-ja.com

符号付き整数オーバーフローはまだC ++で未定義の動作ですか?

知っているように、 符号付き整数オーバーフローは未定義の動作です 。しかし、C++ 11 cstdintドキュメントには興味深いことがあります。

正確にそれぞれ8、16、32、64ビットの幅を持ち、パディングビットを持たない符号付き整数型、および負の値に2の補数を使用(実装が型を直接サポートする場合にのみ提供)

リンクを参照

そしてここに私の質問があります:規格ではint8_tint16_tint32_tおよびint64_t負の数は2の補数ですが、これらの型のオーバーフローは未定義の動作ですか?

編集 C++ 11およびC11標準を確認しましたが、次のようになりました。

C++ 11、§18.4.1:

ヘッダーは、すべての関数、型、およびマクロをC標準の7.20と同じように定義します。

C11、§7.20.1.1:

Typedef名intN_tは、幅N、パディングビットなし、2の補数表現を持つ符号付き整数型を示します。したがって、int8_tは、幅がちょうど8ビットの符号付き整数型を示します。

71
Archie

これらの型のオーバーフローは未定義の動作ですか?

はい C++ 11標準の5/4段落ごと(一般的な式に関して):

式の評価中に、結果が数学的に定義されていない場合、またはその型の表現可能な値の範囲内にない場合、動作は未定義です。 [...]

これらの符号付き型に2の補数表現が使用されるという事実は、これらの型の式を評価するときに2 ^ nを法とする算術演算が使用されることを意味しません。

一方、unsigned算術に関して、規格は明示的に次のように指定しています(段落3.9.1/4):

unsignedと宣言された符号なし整数、-2 ^ nを法とする算術の法則に従うここで、nは整数の特定のサイズの値表現のビット数

これは、符号なし算術演算の結果は常に「数学的に定義された」であり、結果は常に表現可能な範囲内であることを意味します。したがって、5/4は適用されません。脚注46はこれを説明しています:

46)これは、nsigned算術演算がオーバーフローしないことを意味します。これは、結果の符号なし整数型で表現できない結果が、結果の符号なし整数型。

68
Andy Prowl

型が2の補数表現を使用するように定義されているからといって、その型の算術オーバーフローが定義されるようになるわけではありません。

符号付き算術オーバーフローの未定義の動作は、最適化を有効にするために使用されます。たとえば、コンパイラはa > bその後a + 1 > bまた;これは、2番目のチェックを実行する必要がある符号なし算術では、a + 10。また、一部のプラットフォームでは、算術オーバーフローでトラップ信号を生成できます(例: http://www.gnu.org/software/libc/manual/html_node/Program-Error-Signals.html );標準では、これを継続して許可しています。

23
ecatmur

そうだろう。

標準ドキュメント(pg。4および5)から:

1.3.24未定義の動作

この国際規格が要件を課していない行動

[注:この国際標準が動作の明示的な定義を省略している場合、またはプログラムが誤った構造または誤ったデータを使用している場合、未定義の動作が予想される場合があります。許容される未定義の動作は、予測不可能な結果を​​伴う状況を完全に無視することから、環境に特有の文書化された方法での動作中の動作(診断メッセージの発行の有無にかかわらず)、翻訳または実行の終了(発行による)診断メッセージの)。多くの誤ったプログラム構造は、未定義の動作を引き起こしません。診断する必要があります。

1
EnzoR