WARNING: overly technical explanation below
Note that this behavior is applicable to
2's compliment machines only. Granted this is virtually all platforms nowadays, but in case you come across a non 2's compliment machine the behavior will be different.
Numbers are stored as binary data. Each bit has a "weight" of 2
n where 'n' is the bit index.
That is:
bit 0 = weight of 2
0 = 1
bit 1 = weight of 2
1 = 2
bit 2 = weight of 2
2 = 4
(Where bit 0 is the lowest bit)
The weight of the bits that are "on" (set) are effectively summed to produce the number. So if you have the following number in binary:
1 2 3 4
|
%00101100 <- number in binary
^ ^^
| ||
76543210 <- bit number (n)
|
as you can see bits 2, 3, and 5 are "on", so this number is:
2
2 + 2
3 + 2
5
= 4 + 8 + 32
= 44
Therefore 8 bit unsigned numbers effectively have a range of 0 (%00000000) to 255 (%11111111).
Signed numbers just make the weight of the highest bit negative. So for unsigned 8-bit numbers, the weight of the highest bit (bit 7) is 128. But for a
signed 8-bit number, the weight is -128
For example:
1 2 3 4
|
%10000001
unsigned = 1 + 128 = 129
signed = 1 + -128 = -127
|
Therefore signed 8 bit numbers effectively have a range of -128 (%10000000) to 127 (%01111111)
16-bit numbers are the same way, only the highest bit is bit 15 (weight of +/- 32768 depending on sign).
Now when you copy an unsigned variable (or a wider variable) to a signed var (or a var with fewer bits), the computer just stupidly copies over the bits, without giving thought to what the bits actually represent. So back to your original code:
1 2 3 4
|
short int i;
int j;
j = 60000;
i = j;
|
j is a 32-bit integer containing the number 60000. This means it contains the following bits:
j: 00000000000000001110101001100000
When you copy j to i on line 4, since i is a smaller type (only 16 bits), the computer drops the high 16 bits and only copies the low 16 bits:
1 2
|
j: 00000000000000001110101001100000
i: 1110101001100000
|
And of course, since the high bit has a negative weight, this produces a strangely different negative number instead of the expected 60000.