知っているように、 符号付き整数オーバーフローは未定義の動作です 。しかし、C++ 11 cstdint
ドキュメントには興味深いことがあります。
正確にそれぞれ8、16、32、64ビットの幅を持ち、パディングビットを持たない符号付き整数型、および負の値に2の補数を使用(実装が型を直接サポートする場合にのみ提供)
そしてここに私の質問があります:規格ではint8_t
、int16_t
、int32_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ビットの符号付き整数型を示します。
これらの型のオーバーフローは未定義の動作ですか?
はい C++ 11標準の5/4段落ごと(一般的な式に関して):
式の評価中に、結果が数学的に定義されていない場合、またはその型の表現可能な値の範囲内にない場合、動作は未定義です。 [...]
これらの符号付き型に2の補数表現が使用されるという事実は、これらの型の式を評価するときに2 ^ nを法とする算術演算が使用されることを意味しません。
一方、unsigned算術に関して、規格は明示的に次のように指定しています(段落3.9.1/4):
unsigned
と宣言された符号なし整数、-2 ^ nを法とする算術の法則に従うここで、nは整数の特定のサイズの値表現のビット数
これは、符号なし算術演算の結果は常に「数学的に定義された」であり、結果は常に表現可能な範囲内であることを意味します。したがって、5/4は適用されません。脚注46はこれを説明しています:
46)これは、nsigned算術演算がオーバーフローしないことを意味します。これは、結果の符号なし整数型で表現できない結果が、結果の符号なし整数型。
型が2の補数表現を使用するように定義されているからといって、その型の算術オーバーフローが定義されるようになるわけではありません。
符号付き算術オーバーフローの未定義の動作は、最適化を有効にするために使用されます。たとえば、コンパイラはa > b
その後a + 1 > b
また;これは、2番目のチェックを実行する必要がある符号なし算術では、a + 1
は0
。また、一部のプラットフォームでは、算術オーバーフローでトラップ信号を生成できます(例: http://www.gnu.org/software/libc/manual/html_node/Program-Error-Signals.html );標準では、これを継続して許可しています。
そうだろう。
標準ドキュメント(pg。4および5)から:
1.3.24未定義の動作
この国際規格が要件を課していない行動
[注:この国際標準が動作の明示的な定義を省略している場合、またはプログラムが誤った構造または誤ったデータを使用している場合、未定義の動作が予想される場合があります。許容される未定義の動作は、予測不可能な結果を伴う状況を完全に無視することから、環境に特有の文書化された方法での動作中の動作(診断メッセージの発行の有無にかかわらず)、翻訳または実行の終了(発行による)診断メッセージの)。多くの誤ったプログラム構造は、未定義の動作を引き起こしません。診断する必要があります。