ゼロ除算の例外が発生しない理由がよくわかりません。
int d = 0;
d /= d;
ゼロ除算の例外を取得することを期待していましたが、代わりにd == 1
。
d /= d
ゼロ除算の例外をスローしないのはなぜd == 0
ですか?
ゼロ除算の例外が発生しない理由がよくわかりません。
int d = 0;
d /= d;
ゼロ除算の例外を取得することを期待していましたが、代わりにd == 1
。
d /= d
ゼロ除算の例外をスローしないのはなぜd == 0
ですか?
throw
ステートメントによってスローされます。他には何もありません(未定義の振る舞いの土地にいる場合を除く)。
回答:
C ++には、キャッチする「ゼロ除算」例外はありません。観察している動作は、コンパイラの最適化の結果です。
d == 0
)の未定義の振る舞いの条件が発生してはならないと推測します。d / d
常に1に等しくなければなりません。コードを少し調整するだけで、コンパイラにゼロによる「実際の」除算をトリガーさせることができます。
volatile int d = 0;
d /= d; //What happens?
だから今、疑問が残ります:基本的にコンパイラにこれが起こることを許可するように強制したので、何が起こりますか?これは未定義の動作ですが、コンパイラがこの未定義の動作を最適化できないようにしました。
ほとんどの場合、ターゲット環境によって異なります。これは、ソフトウェア例外をトリガしないであろうが、それはすることができるハードウェア例外をトリガする(ターゲットCPUに依存する)(整数、ゼロによる除算)、ソフトウェア例外をキャッチすることができる伝統的な方法で捕獲することができません。これは間違いなくx86CPU、および他のほとんどの(すべてではありません!)アーキテクチャに当てはまります。
ただし、プログラムをクラッシュさせるだけでなく、ハードウェア例外(発生した場合)を処理する方法があります。適用可能ないくつかの方法については、この投稿を参照してください。例外のキャッチ:ゼロ除算。それらはコンパイラごとに異なることに注意してください。
1
は、生産が完全に有効なものであるということだけです。14684554を取得するのは、コンパイラがさらに最適化するためである必要があります。初期d==0
条件を伝播するため、「これは1またはUBのいずれか」だけでなく、実際には「これはUB、期間」と結論付けることができます。したがって、定数をロードするコードを作成する必要はありません1
。
他の答えを補足するために、ゼロによる除算が未定義の動作であるという事実は、コンパイラーがそれが発生した場合に自由に何でもできることを意味します。
0 / 0 == 1
、それに応じて最適化する場合があります。それは事実上、ここで行ったように見えることです。0 / 0 == 42
設定d
することもできます。d
が不確定であると判断し、変数を初期化しないままにして、その値が、割り当てられたメモリに以前に書き込まれたものになります。コメントで他のコンパイラーで観察された予期しない値のいくつかは、それらのコンパイラーがこのようなことをしていることが原因である可能性があります。d
、コンパイル時にの元の値がわからなかったとしても、コンパイラーはそれがゼロになることはないと想定し、それに応じてコードを最適化することができます。OPのコードの特定のケースでは、これは、と仮定するだけでコンパイラと実質的に区別できません0 / 0 == 1
が、コンパイラは、たとえば、puts()
inif (d == 0) puts("About to divide by zero!"); d /= d;
が実行されないと仮定することもできます。ゼロによる整数除算の動作は、C ++標準では定義されていません。例外をスローする必要はありません。
(浮動小数点のゼロ除算も定義されていませんが、IEEE754で定義されています。)
コンパイラは最適化さd /= d
れており、効果的にd = 1
これを選択するのが妥当です。コードに未定義の動作がないと想定できるため、この最適化を行うことがd
できます。つまり、ゼロになることはできません。
d
おそらくゼロになることはできない」と仮定するのが合理的であると言うとき、コンパイラが次の行を認識しないと仮定しますint d = 0;
か?:)
この場合(およびその他の場合)、ブーストセーフ数値を使用してコードでC ++例外を生成できることに注意してください。https://github.com/boostorg/safe_numerics