简体   繁体   English

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

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

I want signed integers to overflow when they become too big. 希望签名整数在它们变得太大时溢出。 How do I achieve that without using the next biggest datatype (or when I am already at int128_t)? 如何在不使用下一个最大数据类型的情况下(或者当我已经在int128_t时)实现这一目标?

For example using 8bit integers 19*12 is commonly 260, but I want the result 1 11 10 01 00 with the 9th bit cut off, thus -27. 例如,使用8位整数19 * 12通常为260,但我希望结果为1 11 10 01 00 ,第9位被截止,因此为-27。

Signed overflow is undefined in C, and that's for real . 签名溢出在C中是未定义的, 这是真实的

One solution follows: 一个解决方案如下

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

The above solution involves implementation-defined behavior in the final conversion from unsigned to int but do not invoke undefined behavior. 上述解决方案涉及从unsignedint的最终转换中的实现定义行为,但不调用未定义的行为。 With most compilation platforms' implementation-defined choices, the result is exactly the two's complement result that you expect. 对于大多数编译平台的实现定义选择,结果正是您期望的两个补码结果。

Finally, an optimizing compiler for one of the numerous platforms on which implementation-defined choices force the compiler to give you the behavior you expect will compile the above code to the obvious assembly instruction. 最后, 针对实现定义的选择迫使编译器为您提供所期望的行为的众多平台之一的优化编译器将上述代码编译为明显的汇编指令。

Alternately, if you are using gcc, then the options -fwrapv / -fno-strict-overflow may be exactly what you want. 或者,如果您正在使用gcc,那么选项-fwrapv / -fno-strict-overflow可能正是您想要的。 They provide an additional guarantee with respect to the standard that signed overflows wrap around. 它们提供了有关签名溢出的标准的额外保证。 I'm not sure about the difference between the two. 我不确定两者之间的区别。

Signed integer overflow is undefined according to both C and C++ standards. 根据C和C ++标准,未定义有符号整数溢出。 There's no way to accomplish what you want without a specific platform in mind. 没有特定的平台,没有办法实现你想要的。

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

It sounds like you want to do unsinged integer arithmetic, then stuff the result into a signed integer: 听起来你想要做一些未编组的整数运算,然后将结果填充到有符号整数中:

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

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

should give you what you're looking for. 应该给你你想要的东西。 Let us know if it doesn't. 如果没有,请告诉我们。

Assuming two's complement signed integer arithmetic (which is a reasonable assumption these days), for addition and subtraction, just cast to unsigned to do the calculation. 假设有两个补码有符号整数运算(这些天是合理的假设),对于加法和减法,只需转换为无符号进行计算。 For multiplication and division, ensure the operands are positive, cast to unsigned, calculate and adjust the signs. 对于乘法和除法,确保操作数为正,转换为无符号,计算和调整符号。

It is possible to do this in a correct standard C manner, so long as you have access to an unsigned type that is of the same width as your signed type (that is, has one more value bit). 这是可能做到这一点在一个正确的标准C的方式,只要你有机会获得一个unsigned类型,它是相同的宽度为您的signed类型(即,有一个更大的价值位)。 To demonstrate with int64_t : 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;
}

This does not produce any problematic intermediate results. 这不会产生任何有问题的中间结果。

Use bigger datatypes. 使用更大的数据类型。 With GMP you will have all the space you probably need. 使用GMP,您将拥有您可能需要的所有空间。

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

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