# 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`.