1. ホーム
  2. c++

[解決済み] d == 0 のとき 'd /= d' がゼロによる除算の例外を投げないのはなぜですか?

2023-08-04 11:10:06

質問

ゼロによる除算の例外が発生しない理由がよくわかりません。

int d = 0;
d /= d;

ゼロによる除算の例外が発生すると思っていましたが、代わりに d == 1 .

なぜ d /= d がゼロによる除算の例外を投げるのはなぜですか? d == 0 ?

どのように解決するのですか?

C++には、キャッチするための例外("Division by Zero")がありません。あなたが観察している動作は、コンパイラの最適化によってもたらされたものです。

  1. コンパイラーは未定義の動作が発生しないことを想定しています。
  2. C++でゼロによる除算は未定義の動作である
  3. したがって、以下のようなコードは が可能です。 がゼロによる除算を引き起こす可能性があるコードは、そうならないように推定されます。
    • また、以下のようなコード は必ず を引き起こすコードは、ゼロによる除算が発生しないように仮定されます。
  4. したがって、コンパイラは、Undefined Behavior が起こらないので、このコードの Undefined Behavior のための条件 ( d == 0 ) は起こらないはずです。
  5. したがって d / d は常に 1 に等しくなければなりません。

しかし...

あなたのコードに少し手を加えるだけで、コンパイラがゼロによる "real"除算を強制的にトリガーすることができます。

volatile int d = 0;
d /= d; //What happens?

さて、ここで疑問が残ります。基本的にコンパイラにこれを許可するよう強制した結果、何が起こるのでしょうか?これは未定義の動作ですが、私たちはコンパイラーがこの未定義の動作に対して最適化するのを阻止しました。

ほとんどの場合、それはターゲット環境に依存します。これはソフトウェア例外をトリガーしませんが、それは ができます。 (ターゲット CPU に依存) ハードウェア例外 (Integer-Divide-by-Zero) が発生する可能性があり、ソフトウェア例外が捕捉できる従来の方法では捕捉することができません。これは間違いなく x86 CPU のケースであり、他のほとんどのアーキテクチャ (すべてではありません!) でも同じです。

しかし、プログラムをクラッシュさせるのではなく、ハードウェア例外に対処する方法があります (発生した場合)。 例外のキャッチ: ゼロによる除算 . これらはコンパイラによって異なることに注意してください。