I have noticed something weird and I would really appreciate if someone could help me to understand what's happening on a deeper level.
temp1 = 0x3a
temp2 = 0xfb
printf("%x", abs(temp1 - temp2))
will print 0x3f
if temp1, temp2 were of type int8_t
.
will print 0xc1
if temp1, temp2 were of type int16_t
.
will print 0xc1
if temp1, temp2 were of type uint8_t
.
now I understand that int16_8 and uint8_t has bigger positive range, but I still don't understand what's going on, I tried int8_t and to use casting
printf("%x", abs((int16_t) (temp1) - (int16_t)(temp2)))
The program printed 0x3f
(I expected to get 0xc1
) which is really confusing
CodePudding user response:
If temp1
and temp2
have type int8_t
, then temp1 = 0x3a
sets temp1
to 58 (the value of 0x3a
), but it is implementation-defined what temp2 = 0xfb
sets temp2
to, because the value of 0xfb
(251) is too large for int8_t
. Commonly, a C implementation will set it to −5 (which equals 251−256 and which has the same bit encoding in two’s complement as 251 does in unsigned binary).
Then temp1 - temp2
is 58 − −5 = 63, for which the absolute value is 63, the value of 0x3f
.
If temp1
and temp2
have type int16_t
or uint8_t
, then temp1 = 0x3a
sets temp1
to 58, as before, and temp2 = 0xfb
sets temp2
to 251.
Then temp1 - temp2
is 58 − 251 = −193, for which the absolute value is 193, the value of 0xc1
. Note that, in the evaluation of temp1 - temp2
, values of type int16_t
or uint8_t
are automatically promoted to int
, so the arithmetic is done using the int
type and produces −193 even if the types of temp1
and temp2
are uint8_t
.