[英]Binary Addition without overflow wrap-around in C/C++
I know that when overflow occurs in C/C++, normal behavior is to wrap-around. 我知道,当C / C ++中发生溢出时,正常行为是绕回。 For example,
INT_MAX+1
is an overflow. 例如,
INT_MAX+1
是一个溢出。
Is possible to modify this behavior, so binary addition takes place as normal addition and there is no wraparound at the end of addition operation ? 是否可以修改此行为,因此二进制加法会像普通加法一样发生,并且加法操作结束时没有回绕?
Some Code so this would make sense. 一些代码,所以这很有意义。 Basically, this is one bit (full) added, it adds bit by bit in 32
基本上,这是一个(全部)添加,它在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;
}
If I try to adder(INT_MAX, 1);
如果我尝试
adder(INT_MAX, 1);
it actually overflows, even though, I amn't using +
operator. 它实际上溢出了,即使我没有使用
+
运算符。
Thanks ! 谢谢 !
Overflow means that the result of an addition would exceed std::numeric_limits<int>::max()
(back in C days, we used INT_MAX
). 溢出意味着相加的结果将超过
std::numeric_limits<int>::max()
(在C天之内,我们使用INT_MAX
)。 Performing such an addition results in undefined behavior. 执行此类加法会导致未定义的行为。 The machine could crash and still comply with the C++ standard.
机器可能会崩溃,但仍然符合C ++标准。 Although you're more likely to get
INT_MIN
as a result, there's really no advantage to depending on any result at all. 尽管您更有可能获得
INT_MIN
的结果,但是完全依赖于任何结果实际上没有任何优势。
The solution is to perform subtraction instead of addition, to prevent overflow and take a special case: 解决方案是执行减法而不是加法,以防止溢出并采取特殊情况:
if ( number > std::numeric_limits< int >::max() - 1 ) { // ie number + 1 > max
// fix things so "normal" math happens, in this case saturation.
} else {
++ number;
}
Without knowing the desired result, I can't be more specific about the it. 在不知道所需结果的情况下,我无法对其进行更具体的说明。 The performance impact should be minimal, as a rarely-taken branch can usually be retired in parallel with subsequent instructions without delaying them.
对性能的影响应该最小,因为很少使用的分支通常可以与后续指令同时退出而不会延迟它们。
Edit: To simply do math without worrying about overflow or handling it yourself, use a bignum library such as GMP . 编辑:要简单地做数学而不用担心溢出或自己处理它,请使用bignum库,例如GMP 。 It's quite portable, and usually the best on any given platform.
它非常便携,通常是任何给定平台上最好的。 It has C and C++ interfaces.
它具有C和C ++接口。 Do not write your own assembly.
不要写你自己的组件。 The result would be unportable, suboptimal, and the interface would be your responsibility!
结果将是不可移植的,次优的,并且接口将由您负责!
不,您必须手动添加它们以检查是否溢出。
What do you want the result of INT_MAX + 1
to be? 您希望
INT_MAX + 1
的结果是什么? You can only fit INT_MAX
into an int
, so if you add one to it, the result is not going to be one greater. 您只能将
INT_MAX
装入一个int
,因此,如果将int
加上一个,则结果将不会 INT_MAX
。 ( Edit: On common platforms such as x86 it is going to wrap to the largest negative number: -(INT_MAX+1)
. The only way to get bigger numbers is to use a larger variable. ( 编辑:在常见的平台上,例如x86,它将包装为最大的负数
-(INT_MAX+1)
。获取更大数字的唯一方法是使用更大的变量。
Assuming int
is 4-bytes (as is typical on x86 compilers) and you are executing an add
instruction (in 32-bit mode), the destination register simply does overflow -- it is out of bits and can't hold a larger value. 假设
int
为4字节(如x86编译器中的典型值),并且您正在执行add
指令(在32位模式下),则目标寄存器只是发生溢出 -它用完了位并且不能容纳更大的值。 It is a limitation of the hardware. 这是硬件的限制。
To get around this, you can hand-code, or use an aribitrarily-sized integer library that does the following: 要解决此问题,您可以手动编码,或使用执行以下操作的任意大小的整数库:
add
instruction on the lowest-order words. add
指令。 If overflow occurs, the Carry flag is set. adc
instruction, which adds the two operands as usual, but takes into account the value of the Carry flag (as a value of 1.) adc
指令,该指令照常将两个操作数相加,但要考虑到进位标志的值(值为1)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.