Suppose we have three integer (int, long, long long, unsigned int, etc) variables a, b, c. Normally, performing
c = a / b;
would result in truncate of fractions. However, is it possible for c
to end up with an incorrect value? I am not talking about a / b may be out of range for c's type.
It should not be possible that for example the last digit of division be wrong, if all rules were followed otherwise. C11 6.5.5p6:
When integers are divided, the result of the /
operator is the algebraic quotient with any fractional part discarded.
i.e. the result is not "close" to but exactly the same as a / b would be algebraically, just anything following the point discarded.
That does not mean there won't be any gotchas: it is possible that the division of a / b
might be mathematically not out of range for c
's type yet out of range for the type used in the division itself which can cause wrong values be set in c.
Consider this example:
#include <stdio.h>
#include <inttypes.h>
int main(void) {
int32_t a = INT32_MIN;
int32_t b = -1;
int64_t c = a / b;
printf("%" PRId64, c);
}
The result of division of INT32_MIN / -1
is representable in c
, it is INT32_MAX + 1
, which is positive. However on 32-bit platforms the arithmetic happens in 32 bits, and this division produces an integer overflow which causes the behaviour to be undefined. What happens on my computer is that if I compile without optimizations it aborts the program. If I compile with optimizations enabled (-O3
), the compiler will resolve this calculation at compilation time, and handles the overflow in a peculiar way and produces the result -2147483648
which is negative.
Likewise, if you do this:
uint16_t a = 16;
int16_t b = -1;
int32_t result = a / b;
printf("%" PRId32 "\n", result);
the result on a 32-bit int machine is -16. If you change the type of a
to uint32_t
the math happens in unsigned:
uint32_t a = 16;
int16_t b = -1;
int32_t result = a / b;
printf("%" PRId32 "\n", result);
The result is of course 0
. And you would get 0
from the former calculation too on a 16-bit machine.