我知道当C / C ++发生溢出时,正常的行为是环绕。例如,INT_MAX+1
是溢出的。
是否可以修改此行为,因此二进制添加是作为正常添加进行的,并且在添加操作结束时没有回绕?
一些代码,所以这是有道理的。基本上,这是一位(完整)添加,它在32
中逐位添加int adder(int x, int y)
{
int sum;
for (int i = 0; i < 31; i++)
{
sum = x ^ y;
int carry = x & y;
x = sum;
y = carry << 1;
}
return sum;
}
如果我尝试adder(INT_MAX, 1);
它实际上会溢出,即使我没有使用+
运算符。
谢谢!
答案 0 :(得分:4)
溢出意味着添加的结果将超过std::numeric_limits<int>::max()
(回到C天,我们使用INT_MAX
)。执行此类添加会导致未定义的行为。机器可能崩溃,仍然符合C ++标准。虽然你更有可能得到INT_MIN
,但依赖任何结果都没有任何优势。
解决方案是执行减法而不是添加,以阻止溢出并采取特殊情况:
if ( number > std::numeric_limits< int >::max() - 1 ) { // ie number + 1 > max
// fix things so "normal" math happens, in this case saturation.
} else {
++ number;
}
在不知道所需结果的情况下,我无法对其进行更具体的了解。性能影响应该是最小的,因为很少采用的分支通常可以与后续指令同时退役,而不会延迟它们。
修改:要简单地进行数学计算而不必担心溢出或自行处理,请使用bignum库,例如GMP。它非常便携,通常在任何给定平台上都是最好的。它有C和C ++接口。 不编写自己的程序集。结果将是不可移植的,次优的,界面将是您的责任!
答案 1 :(得分:2)
不,您必须手动添加它们以检查溢出。
答案 2 :(得分:1)
您希望INT_MAX + 1
的结果是什么?您只能将INT_MAX
放入int
,因此如果您添加一个,结果不将更大。 (编辑:在诸如x86 之类的常见平台上,它将包装到最大的负数:-(INT_MAX+1)
。获得更大数字的唯一方法是使用更大的变量。
假设int
是4字节(在x86编译器上是典型的)并且您正在执行add
指令(在32位模式下),目标寄存器只是溢出< / em> - 它没有位,不能容纳更大的值。这是硬件的限制。
要解决此问题,您可以手动编码,或使用执行以下操作的任意大小的整数库:
add
指令。如果发生溢出,则设置进位标志。adc
指令,它会照常添加两个操作数,但会考虑Carry标志的值(值为1。)您可以看到64位值here。