c++ - 为什么当 d == 0 时 'd/= d' 不抛出被零除异常?

标签 c++ compiler-optimization undefined-behavior division divide-by-zero

我不太明白为什么我没有得到被零除的异常:

int d = 0;
d /= d;

我原本希望得到除以零的异常,但结果却是 d == 1

为什么当d == 0d/= d不抛出被零除异常?

最佳答案

C++ 没有要捕获的“除零”异常。您观察到的行为是编译器优化的结果:

  1. 编译器假定未定义行为不会发生
  2. C++ 中的除零是未定义的行为
  3. 因此,可能导致被零除的代码被认为不会这样做。
    • 并且,必须导致被零除的代码被假定永远不会发生
  4. 因此,编译器推断,由于未定义行为不会发生,因此此代码中未定义行为的条件 (d == 0) 一定不会发生
  5. 因此,d/d 必须始终等于 1。

但是...

我们可以通过对代码进行细微调整来强制编译器触发“真正的”除以零。

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

所以现在的问题仍然是:现在我们基本上已经强制编译器允许这种情况发生,会发生什么?这是未定义的行为,但我们现在已经阻止编译器围绕这种未定义的行为进行优化。

大多数情况下,这取决于目标环境。这不会触发软件异常,但它可以(取决于 objective-c PU)触发硬件异常(整数除以零),而软件无法以传统方式捕获该异常可以捕获异常。对于 x86 CPU 和大多数其他(但不是全部!)架构来说绝对是这种情况。

但是,有一些方法可以处理硬件异常(如果发生),而不仅仅是让程序崩溃:请查看这篇文章以了解一些可能适用的方法:Catching exception: divide by zero 。请注意,它们因编译器而异。

关于c++ - 为什么当 d == 0 时 'd/= d' 不抛出被零除异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57628986/

相关文章:

c++ - 编译错误 : "no matching function for call to" when returning static_cast reference

C++ 将一个参数默认为另一个参数

c++ - 在 C 和 C++ 中,使用逗号运算符(如 "a = b,++a;")的表达式是否未定义?

c++ - "Materializing"用于 C++ 类型推断的已知类型的对象

c++ - 在 C++11 中返回可变值

c++:初始化静态字符串成员

编译器标志更改代码行为(O2、Ox)

c++ -/fp :fast 的奇怪结果

c++ - 具有不匹配优化级别(-O3、-O2、-O1、-O0)的二进制文件是否会导致稳定性问题?

c++ - 在带有初始化的声明中,我可以使用对未初始化数据的引用吗?