Catching Integer Overflows in C
fefe.de
fefe.de
If you need the information then the straightforward thing to do is not to discard it in the first place.
...and after a quick bit of googling, it appears this has been discussed by the GCC devs semi-recently: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48580
volatile int b = 23;
if (a + b < b) overflow;
Tada. That's how you get around the GCC optimization issue in practice. I suppose though this doesn't suite as a proper answer since overflowing as a result of adding two signed integers results in undefined behavior..The solution is to cast the integers to unsigned and then do the overflow check. The following two standard sections should demonstrate the standards-compliance of the code below.
> ANSI C99 6.2.5 Types #9
> A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type.
> ANSI C99 6.3.1.3 Signed and unsigned integers #2
> Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.
---------
// shift the MSB to the LSB
#define signof(x) (!!((x) & INT_MIN))
int x, y;
// bits stay the same thanks to 6.3.1.3
unsigned int a = (unsigned int) x;
unsigned int b = (unsigned int) y;
unsigned int sign_a = signof(a);
unsigned int sign_b = signof(b);
// a+b should have the same sign as a and b, otherwise an overflow/underflow has occurred
// note that a+b is well defined for unsigned ints according to 6.2.5 #9
if (sign_a == sign_b && signof(a+b) != sign_a) overflow;
The code for checking overflow on unsigned ints is trivial: unsigned int a, b;
if (a + b < a) overflow;> Since the addition operation in the CPU is agnostic to whether the integer is signed or unsigned, the same goes for signed integers.
> So, if you want to add two integers a and b (b >= 0), the easiest way to find out if that overflows is to check whether a+b<a (or b; some people think you have to check against min(a,b), but that is unnecessary).
This statement is untrue, as is the other statement I quoted.
The proper way to do this is still
if (a > UINT_MAX - b)
errx(1, "Too large.");
a += b;
and variants.https://github.com/rplnt/personal/blob/master/C/fractions/zl...
Edit: The C99 standard acknowledges that abs(INT_MIN) isn't representable, so using abs(INT_MIN) is undefined.
Further, x86 only provides these SIMD operations on 8-bit and 16-bit quantities, not on 32-bit or 64-bit quantities (although all these types can be packed into a SIMD register and operated on with at least some operations; for example regular, non-saturating add).
SSE has a menagerie of non-orthogonal oddities, unfortunately; this is only one of them.
http://msdn.microsoft.com/en-us/library/dd570023.aspx http://safeint.codeplex.com/