我用c++写了一个程序来寻找ab = C的所有解,其中a, b和C一起使用所有的数字0-9,只使用一次。程序循环遍历a和b的值,并每次对a、b和ab运行数字计数例程,以检查是否满足数字条件。

但是,当ab超出整数限制时,会产生伪解。我最终使用如下代码来检查这个:

unsigned long b, c, c_test;
...
c_test=c*b;         // Possible overflow
if (c_test/b != c) {/* There has been an overflow*/}
else c=c_test;      // No overflow

是否有更好的方法来测试溢出?我知道有些芯片有一个内部标志,在溢出发生时设置,但我从未见过通过C或c++访问它。


注意,有符号int溢出在C和c++中是未定义的行为,因此您必须在不实际引起它的情况下检测它。对于加法前的有符号整型溢出,请参见在C/ c++中检测有符号溢出。


当前回答

用double计算结果。它们有15位有效数字。您的要求在c上有一个硬上限108 -它最多可以有8位数字。因此,如果它在范围内,结果将是精确的,否则它将不会溢出。

其他回答

CERT开发了一种新方法,使用“as-if”无限范围(AIR)整数模型来检测和报告有符号整数溢出、无符号整数包装和整数截断。CERT已经发布了一份描述该模型的技术报告,并生成了一个基于GCC 4.4.0和GCC 4.5.0的工作原型。

AIR整数模型产生的值与使用无限范围整数所获得的值相等,或者导致违反运行时约束。与之前的整数模型不同,AIR整数不需要精确的陷阱,因此不会破坏或抑制大多数现有的优化。

一种简单的方法是重写所有操作符(特别是+和*),并在执行操作之前检查是否有溢出。

最简单的方法是将unsigned long转换为unsigned long,进行乘法运算,并将结果与0x100000000LL进行比较。

你可能会发现这比你在例子中做除法更有效。

哦,它在C和c++中都可以工作(因为你已经用这两种语言标记了问题)。


我在看glibc手册。这里提到了整数溢出陷阱(FPE_INTOVF_TRAP)作为SIGFPE的一部分。这将是理想的,除了手册中令人讨厌的部分:

FPE_INTOVF_TRAP 整数溢出(在C程序中不可能,除非您以特定于硬件的方式启用溢出捕获)。

真的有点遗憾。

x86指令集包括一个无符号乘法指令,它将结果存储到两个寄存器中。要使用C中的指令,可以在64位程序(GCC)中编写以下代码:

unsigned long checked_imul(unsigned long a, unsigned long b) {
  unsigned __int128 res = (unsigned __int128)a * b;
  if ((unsigned long)(res >> 64))
    printf("overflow in integer multiply");
  return (unsigned long)res;
}

对于32位程序,需要使结果为64位,参数为32位。

另一种方法是使用依赖于编译器的intrinsic来检查标志寄存器。关于溢出的GCC文档可以从6.56内置函数执行溢出检查算术中找到。

不能从C/ c++中访问溢出标志。

我不同意这种说法。您可以编写一些内联汇编语言并使用jo(跳转溢出)指令,假设您在x86上捕获溢出。当然,您的代码将不再能够移植到其他体系结构。

查看info as和info gcc。