The code:
int main(void) {
uint8_t x = 3;
uint8_t y = 4;
uint8_t z = 5;
uint8_t a = (x - y) / z;
uint8_t b = x - y;
printf("a is %d\n", a);
printf("b is %d\n", b);
return 0;
}
had the following output:
a is 0
b is 255
I would expect that (3 - 4) / 5
would result in an overflow as (3 - 4)
as a uint8_t
is 255. When an intermediate step involving unsigned integers results in a negative number, why doesn't it overflow? In what format is the result for (3 - 4)
stored before the next step / 5
happens?
One can use a much simpler example to see what's really going on:
#include <stdio.h>
#include <stdint.h>
int main(void) {
uint8_t x = 3;
uint8_t y = 4;
int a = (x - y);
printf("a is %d\n", a); // a is -1
return 0;
}
(Live example: http://ideone.com/C3SlIn)
What you're seeing there is the result of the integer promotions that are performed on the operands to -
as part of the usual arithmetic conversions.1 Relevant parts of the definition of integer promotions from the (C99) standard:
[6.3.1.1] If an
int
can represent all values of the original type, the value is converted to anint
; otherwise, it is converted to anunsigned int
.
An int
can indeed represent all values of a uint8_t
, so that subtraction is really equivalent to:
int a = (int)x - (int)y;
In other words, there is no overflow.
1. But to preempt one common confusion, this behaviour is inherent to how -
works; it's not because we're assigning to an int
here.