在C / C ++中允许有符号的整数溢出
当他们变得太大时,我想要有符号整数溢出。 如何在不使用下一个最大的数据types(或者当我已经在int128_t时)实现这个function?
例如,使用8位整数19 * 12通常是260,但是我想要结果1 11 10 01 00
与第9位切断,因此-27。
C中的未定义的溢出, 这是真实的 。
一个解决scheme如下
signed_result = (unsigned int)one_argument + (unsigned int)other_argument;
上面的解决scheme涉及从unsigned
到int
的最终转换中实现定义的行为,但不要调用未定义的行为。 在大多数编译平台的实现定义的select中,结果正是您所期望的二进制补码结果。
最后, 对于实现定义的select强制编译器给你所期望的行为的众多平台之一的优化编译器将编译上述代码到显而易见的汇编指令。
或者,如果您使用的是gcc,则选项-fwrapv
/ -fno-strict-overflow
可能正是您想要的。 它们提供了一个额外的保证,相对于标志溢出环绕的标准。 我不确定两者的区别。
根据C和C ++标准,有符号整数溢出未定义。 没有一个特定的平台,没有办法完成你想要的东西。
你可以创build一个int的目标包装,但这将涉及到相当多的开销代码。
这听起来像你想做unsinged整数算术,然后将结果填充到一个有符号的整数:
unsigned char a = 19; unsigned char b = 12; signed char c = (signed char)(a*b);
应该给你你想要的。 让我们知道如果没有。
假设二进制补码有符号整数运算(这是一个合理的假设,这些天),加法和减法,只是投无符号做计算。 对于乘法和除法,确保操作数是正的,转换为无符号的,计算和调整符号。
只要你有权访问与unsigned
types相同宽度的无signed
types(也就是说,有一个更多的值),就可以用正确的标准C方式来执行此操作。 用int64_t
来演示:
int64_t mult_wrap_2scomp(int64_t a, int64_t b) { uint64_t result = (uint64_t)a * (uint64_t)b; if (result > INT64_MAX) return (int64_t)(result - INT64_MAX - 1) - INT64_MAX - 1; else return (int64_t)result; }
这不会产生任何有问题的中间结果。
使用更大的数据types。 使用GMP,您将拥有您可能需要的所有空间。