tags:

views:

623

answers:

5

Lets take the code

int a, b, c;
...
if ((a + b) > C)

If the values of a and b add to exceed the max value of an int will the integrity of the comparison be compromised? I was thinking that there might be an implicit up cast or overflow bit checked and factored into the evaluation of this expression.

+8  A: 

C will do no such thing. It will silently overflow and lead to a possibly incorrect comparison. You can up-cast yourself, but it will not be done automatically.

hazzen
Agree! No self-respecting C compiler will ever do this. SILENTLY OVERFLOW BABY! And we wouldn't have it any other way. This is what's great about C, after all.
James D
A: 

I believe this might be platform specific. Check the C documentation on how overflows are handled...

Ah, yes, and the upcast will not happen automatically...

Daren Thomas
A: 

See section 2.7, Type Conversions in the K&R book

cwick
+2  A: 

A test confirms that GCC 4.2.3 will simply compare with the overflowed result:

#include <stdio.h>

int main()
{
    int a, b, c;

    a = 2000000000;
    b = 2000000000;
    c = 2100000000;

    printf("%d + %d = %d\n", a, b, a+b);
    if ((a + b) > c)
    {
        printf("%d + %d > %d\n", a, b, c);
    }
    else
    {
        printf("%d + %d < %d\n", a, b, c);
    }
    return 0;
}

Displays the following:

2000000000 + 2000000000 = -294967296
2000000000 + 2000000000 < 2100000000
Rob Pilkington
A: 

If upcasting doesn't gain you any bits (there's no guarantee that sizeof(long)>sizeof(int) in C), you can use conditions like the ones below to compare and check for overflow—upcasting is almost certainly faster if you can use it, though.

#if !defined(__GNUC__) || __GNUC__<2 || (__GNUC__==2 && __GNUC_MINOR__<96)
#   define unlikely(x) (x)
#else
#   define unlikely(x)     (__extension__ (__builtin_expect(!!(x), 0)))
#endif

/* ----------
 * Signed comparison (signed char, short, int, long, long long)
 * Checks for overflow off the top end of the range, in which case a+b must
 * be >c.  If it overflows off the bottom, a+b < everything in the range. */
if(a+b>c || unlikely(a>=0 && b>=0 && unlikely(a+b<0)))
    ...

/* ----------
 * Unsigned comparison (unsigned char, unsigned short, unsigned, etc.)
 * Checks to see if the sum wrapped around, since the sum of any two natural
 * numbers must be >= both numbers. */
if(a+b>c || unlikely(a+b<a))
    ...

/* ----------
 * To generate code for the above only when necessary: */
if(sizeof(long)>sizeof(int) ? ((long)a+b>c)
       : (a+b>c || unlikely(a>=0 && b>=0 && unlikely(a+b<0)))
    ...

Great candidates for macros or inline functions. You can pull the "unlikely"s if you want, but they can help shrink and speed up the code GCC generates.