1. ホーム
  2. c++

[解決済み】符号なし整数のオーバーフローは定義されているのに、符号あり整数のオーバーフローは定義されていないのはなぜですか?

2022-04-19 10:36:14

質問

符号なし整数のオーバーフローは、CとC++の両方の標準規格できちんと定義されています。 例えば C99規格 ( §6.2.5/9 ) の状態

符号なしオペランドを含む計算がオーバーフローすることはない。 なぜなら、結果の符号なし整数型で表現できない結果は の最大値より1つ大きい数で減数されます。 で表現される。

しかし、どちらの規格も符号付き整数のオーバーフローは未定義の動作であると述べています。 ここでも、C99標準から( §3.4.3/1 )

未定義の動作の例として、整数のオーバーフローに関する動作があります。

この矛盾には歴史的な理由、あるいは(もっといい!)技術的な理由があるのでしょうか?

解決方法は?

歴史的な理由は、ほとんどのC言語の実装(コンパイラ)は、使用する整数表現で最も実装しやすいオーバーフロー動作をただ使用していたからです。C言語の実装は通常、CPUが使用する整数表現と同じ表現を使用していたため、オーバーフローの動作はCPUが使用する整数表現に従ったものとなっていました。

実際には、実装によって異なるのは符号付き値の表現だけで、1の補数、2の補数、符号-倍数などがあります。符号なし型については、明白な2進表現が1つしかないため、標準がバリエーションを許容する理由はありません(標準は2進表現のみを許容しています)。

関連する引用

C99 6.2.6.1:3 :

符号なしビットフィールド及び符号なしchar型のオブジェクトに格納された値は、純粋なバイナリ表記を使用して表現されなければならない。

C99 6.2.6.2:2 :

符号ビットが 1 の場合、以下のいずれかの方法で値を変更するものとする。

- 符号ビット0に対応する値が否定される ( 符号と大きさ );

- 符号ビットの値は-(2) N ) ( 2の補数 );

- 符号ビットの値は-(2) N - 1) ( 補数 ).


現在、すべてのプロセッサは2の補数表現を使用していますが、符号付き算術オーバーフローは未定義のままであり、コンパイラメーカーはこの未定義を最適化に利用するため、未定義のままにしておきたいのです。例えば、次のようなものがあります。 ブログ記事 イアン・ランス・テイラー、または 苦情 Agner Fog氏によるもので、彼のバグレポートに対する回答です。