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.
-
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.
James D : 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.From hazzen -
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...
From Daren Thomas -
See section 2.7, Type Conversions in the K&R book
From cwick -
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 < 2100000000From Rob Pilkington -
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.
0 comments:
Post a Comment