大型原始数字类型之间的算术:我可以保存溢出吗?

时间:2013-12-11 21:19:34

标签: c++ c math primitive primitive-types

免责声明:我知道,无符号整数是原始数字类型,但它们在技术上不会溢出,我使用的术语是"溢出"对于所有原始数字类型一般来说。

在C或C ++中,根据标准或特定实现,有原始数值类型给定算术运算,即使这个操作可能溢出,我可以保存结果+加上溢出的部分? / p>

即使这听起来很奇怪,我的想法是现代CPU上的寄存器通常比32位float或64位uint64_t大得多,因此有可能实际控制溢出并存放在某处。

4 个答案:

答案 0 :(得分:3)

不,寄存器不是“通常远大于64位uint64_t”。

有一个溢出标志,对于有限数量的操作(加法和减法),将这一个附加位与结果配对足以捕获整个结果范围。

但总的来说,你需要转换为更大的类型(可能在软件中实现)来处理溢出输入类型的结果。

任何执行此类操作的操作(例如,某些32位处理器具有32x32 => 32高,32低宽乘法指令)将由编译器作为内部函数或通过内联汇编提供。 / p>

看,我发现了64位版本,名为Multiply128the matching __mul128 instrinsic available in Visual C++

答案 1 :(得分:2)

请参阅@Ben Voigt关于更大的寄存器。

确实可能只有一个溢出位,可以帮助你。

另一种不采用更宽泛整数的方法是自己测试溢出:

unsigned a,b,sum;
sum = a + b;
if (sum < a) {
  OverflowDetected();  // mathematical result is `sum` + UINT_MAX + 1
}

int的类似方法 以下可能会被简化 - 只是没有它。

[编辑] 我的下面的apporach有潜力UB。有关检测int溢出的更好方法,请参阅Simpler method to detect int overflow

int a,b,sum;
sum = a + b;
// out-of-range only possible when the signs are the same.
if ((a < 0) == (b < 0)) {
  if (a < 0) {
    if (sum > b) UnderflowDetected();
  }
  else {
    if (sum < b) OverflowDetected();
  }

答案 2 :(得分:1)

对于浮点类型,您实际上可以“控制”x86平台上的溢出。使用这些函数"_control87, _controlfp, __control87_2",您可以获取并设置浮点控制字。默认情况下,运行时库会屏蔽所有浮点异常;您可以在代码中取消屏蔽它们,因此当发生溢出时,您将获得异常。但是,我们今天编写的代码都假设浮点异常被屏蔽,所以如果你取消屏蔽它们,你会遇到一些问题。

您可以使用这些functions来获取状态字。

答案 3 :(得分:1)

对于浮点类型,结果由硬件很好地定义,如果不使用C / C ++,你将无法获得太多控制。

对于小于int的整数类型,它们将通过任何算术运算升迁为int。在将结果强制转换为较小的类型之前,您可能能够检测到溢出。

对于加法和减法,您可以通过将结果与输入进行比较来检测溢出。除非存在溢出,否则添加两个正整数将始终产生大于任一输入的结果。