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
In C89 with a 32 bit long
, 2147483648L
has type unsigned long int
(see 3.1.3.2 Integer constants). So once modulo arithmetic has been applied to the unary minus operation, INT32_MIN
is the positive value 2147483648 with type unsigned long
.
In C99, 2147483648L
has type long
if long
is bigger than 32 bits, or long long
otherwise (see 6.4.4.1 Integer constants). So there is no problem and INT32_MIN
is the negative value -2147483648 with type long
or long long
.
Similarly in C89 with long
larger than 32 bits, 2147483648L
has type long
and INT32_MIN
is negative.
I guess you're using a C89 compiler with a 32 bit long
.
One way to look at it is that C99 fixes a "mistake" in C89. In C99 a decimal literal with no U
suffix always has signed type, whereas in C89 it may be signed or unsigned depending on its value.
What you should probably do, btw, is include limits.h
and use INT_MIN
for the minimum value of an int
, and LONG_MIN
for the minimum value of a long
. They have the correct value and the expected type (INT_MIN
is an int
, LONG_MIN
is a long
). If you need an exact 32 bit type then (assuming your implementation is 2's complement):
stdint.h
that works on your C89 compiler, and use int32_t
and INT32_MIN
from that.stdint.h
yourself, and use the expression in WiSaGaN's answer. It has type int
if int
is at least 32 bits, otherwise long
.Replace
#define INT32_MIN (-2147483648L)
with
#define INT32_MIN (-2147483647 - 1)
-2147483648
is interpreted by the compiler to be the negation of 2147483648
, which causes overflow on an int
. So you should write (-2147483647 - 1)
instead.
This is all C89
standard though. See Steve Jessop's answer for C99
.
Also long
is typically 32 bits on 32-bit machines, and 64 bits on 64-bit machines. int
here gets the things done.