I was working on an embedded project when I ran into something which I thought was strange behaviour. I managed to reproduce it on codepad (see below) to confirm, but don't have any other C compilers on my machine to try it on them.
Scenario: I have a #define for the most negative value a 32-bit integer can hold, and then I try to use this to compare with a floating point value as shown below:
#define INT32_MIN (-2147483648L)
void main()
{
float myNumber = 0.0f;
if(myNumber > INT32_MIN)
{
printf("Everything is OK");
}
else
{
printf("The universe is broken!!");
}
}
Codepad link: http://codepad.org/cBneMZL5
To me it looks as though this this code should work fine, but to my surprise it prints out The universe is broken!!.
This code implicitly casts the INT32_MIN to a float, but it turns out that this results in a floating point value of 2147483648.0 (positive!), even though the floating point type is perfectly capable of representing -2147483648.0.
Does anyone have any insights into the cause of this behaviour?
CODE SOLUTION: As Steve Jessop mentioned in his answer, limits.h and stdint.h contain correct (working) int range defines already, so I'm now using these instead of my own #define
PROBLEM/SOLUTION EXPLANATION SUMMARY: Given the answers and discussions, I think this is a good summary of what's going on (note: still read the answers/comments because they provide a more detailed explanation):
- I'm using a C89 compiler with 32-bit
longs, so any values greater thanLONG_MAXand less or equal toULONG_MAXfollowed by theLpostfix have a type ofunsigned long (-2147483648L)is actually a unary-on anunsigned long(see previous point) value:-(2147483648L). This negation operation 'wraps' the value around to be theunsigned longvalue of2147483648(because 32-bitunsigned longs have the range0-4294967295).- This
unsigned longnumber looks like the expected negativeintvalue when it gets printed as anintor passed to a function because it is first getting cast to anint, which is wrapping this out-of-range2147483648around to-2147483648(because 32-bitints have the range -2147483648 to 2147483647) - The cast to
float, however, is using the actualunsigned longvalue2147483648for conversion, resulting in the floating-point value of2147483648.0.