range when doing operations on signed and unsigned integers

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

>Solution :

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.

Leave a Reply