C integer overflow
I was working with integers in C, trying to explore more on when and how overflow happens.
I noticed that when I added two positive numbers, the sum of which overflows, I always got a negative number.
On the other hand, if I added two negative numbers, the sum of which overflows, I always got a positive number (including 0).
I made few experiments, but I would like to know if this is true for every case.
Integer overflows are undefined behavior in C.
C says an expression involving integers overflows, if its result after the usual arithmetic conversions is of a signed typed and cannot be represented in the type of the result. Assignment and cast expressions are an exception as they are ruled by the integer conversions.
Expressions of unsigned type cannot overflow, they wrap, e. g., 0U - 1
is UINT_MAX
.
Examples:
INT_MAX + 1 // integer overflow
UINT_MAX + 1 // no overflow, the resulting type is unsigned
(unsigned char) INT_MAX // no overflow, integer conversion occurs
Never let any integer expression overflows, modern compilers (like gcc
) take advantage of integer overflows being undefined behavior to perform various types of optimizations.
For example:
a - 10 < 20
when a
is of type int
after promotion, the expression is reduced in gcc
(when optimization are enabled) to:
a < 30
It takes advantage of the expression being undefined behavior when a
is in the range INT_MIN + 10 - 1
to INT_MIN
.
This optimization could not be done when a
is unsigned int
because if a
is 0
, then a - 10
has to be evaluated as UINT_MAX - 9
(no undefined behavior). Optimizing a - 10 < 20
to a < 30
would then lead to a different result than the required one when a
is 0
to 9
.
Overflow of signed integers is undefined behaviour in C, so there are no guarantees.
That said, wrap around, or arithmetic modulo 2N, where N
is the number of bits in the type, is a common behaviour. For that behaviour, indeed if a sum overflows, the result has the opposite sign of the operands.