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

问题描述 投票:7回答:8

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

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

c++ c integer-overflow
8个回答
6
投票

在C和that's for real中未定义有符号溢出。

一个解决方案如下

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

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

最后,an optimizing compiler for one of the numerous platforms on which implementation-defined choices force the compiler to give you the behavior you expect将上面的代码编译成明显的汇编指令。

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


3
投票

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


0
投票

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


0
投票

听起来你想做无符号整数运算,然后将结果填充到有符号整数:

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

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

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


0
投票

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


0
投票

只要您可以访问与unsigned类型宽度相同的signed类型(也就是说,还有一个值位),就可以以正确的标准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;
}

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


-1
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.