C variable types
C is a quite low-level programming language, and it does not preserve variable types after compilation. For example, if one had both a unsigned and an unsigned variables of equal size (say uint64_t
and int64_t
), after the compilation ends, each of them will be represented as just an 8-byte piece of memory. All the addition/subtraction will be performed modulo 2 in the corresponding power (64 for 64-bit variables and 32 for 32-bit ones).
The only difference, which remains after compilation is in the comparison. For example, (unsigned) -5 > 1, but -5 < 1. I will explain why now
Your -5 will be stored modulo 2^32, just like every 32-bit value. -5 will be presented as 0xfffffffb in actual ram. The algorithm is simple: if a variable is signed, then it's first bit is called a sign bit and indicates, whether it's positive or negative. The first bit of 0xfffffffb is 1, so, when it comes to signed comparison, it is negative, and is less, than 1. But when compared as an unsigned integer, this value is actually a huge one, 2^32 - 5. So, in general, unsigned representation of a negative signed number is greater by 2^[num of bits in that number]. You can read more about this binary arithmetics here.
So, all, that happened, you got an unsigned number, equal to 0xfffffffb + 0x14 modulo 2^32, which is 0x10000000f (mod 2^32), and that is 0xf = 15.
In conclusion, "%d" assumes it's argument is signed. But that's not the main reason, why the answer happened. However, I advice using %u for unsigned numbers.