繁体   English   中英

在C / C ++中允许有符号整数溢出

[英]Allowing signed integer overflows in C/C++

希望签名整数在它们变得太大时溢出。 如何在不使用下一个最大数据类型的情况下(或者当我已经在int128_t时)实现这一目标?

例如,使用8位整数19 * 12通常为260,但我希望结果为1 11 10 01 00 ,第9位被截止,因此为-27。

签名溢出在C中是未定义的, 这是真实的

一个解决方案如下

signed_result = (unsigned int)one_argument + (unsigned int)other_argument;

上述解决方案涉及从unsignedint的最终转换中的实现定义行为,但不调用未定义的行为。 对于大多数编译平台的实现定义选择,结果正是您期望的两个补码结果。

最后, 针对实现定义的选择迫使编译器为您提供所期望的行为的众多平台之一的优化编译器将上述代码编译为明显的汇编指令。

或者,如果您正在使用gcc,那么选项-fwrapv / -fno-strict-overflow可能正是您想要的。 它们提供了有关签名溢出的标准的额外保证。 我不确定两者之间的区别。

根据C和C ++标准,未定义有符号整数溢出。 没有特定的平台,没有办法实现你想要的。

您可以在int周围创建一个目标包装器,但这将涉及相当多的开销代码。

听起来你想要做一些未编组的整数运算,然后将结果填充到有符号整数中:

unsigned char a = 19;
unsigned char b = 12;

signed char c = (signed char)(a*b);

应该给你你想要的东西。 如果没有,请告诉我们。

假设有两个补码有符号整数运算(这些天是合理的假设),对于加法和减法,只需转换为无符号进行计算。 对于乘法和除法,确保操作数为正,转换为无符号,计算和调整符号。

这是可能做到这一点在一个正确的标准C的方式,只要你有机会获得一个unsigned类型,它是相同的宽度为您的signed类型(即,有一个更大的价值位)。 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;
}

这不会产生任何有问题的中间结果。

使用更大的数据类型。 使用GMP,您将拥有您可能需要的所有空间。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM