Since there are two additions , the highest order bit is used for the sign. By writing a:4 , you say that you only allocate 4 bits of memory, which leaves 3 bits left for the actual number. Therefore, our effective range is [-8,7] . Since all 1 is -1, there is an additional number on the negative side. See the link above for more details.
9, in (unsigned) binary code: 1001 . When you put this in a (signed), you get that a negative, because of the initial 1, and since the next numbers are 001 , we add 1 to the maximum negative number, thereby giving us - 7.
If you want to keep the number 9 in just 4 bits, you need to use unsigned int , which will give you a range of [0, 15] .
EDIT:
In case someone struggles with figuring out how 1001 signed up, gives us -7, consider the following:
Since 1111 is -1, let some variable value = -1 .
To find out the values of the negative (signed) int num , denote x i in num :
x i : {0,1 at position i, where i = 0 is the least significant bit)},
Then for each x i = 0, subtract 2 i from value .
Example:
1001 :
value = -1 - 2 1 - 2 2 = -7