views:

151

answers:

3

Suppose you have the following C code

 unsigned char a = 1;

 printf("%d\n", ~a); // prints -2
 printf("%d\n", a); // prints 1

I am surprised to see -2 printed as a result of ~1 conversion:

Opposite of 0000 0001

is 1111 1110 --> anything but -2

What am i missing here? please advise

+8  A: 
KennyTM
+4  A: 

%d stands for signed decimal number, not unsigned. So your bit pattern, even though it is stored in an unsigned variable, is interpreted as a signed number.

See this Wikipedia entry on signed number representations for an understanding of the bit values. In particular see Two's complement.

Brian R. Bondy
But in a call to a varargs function an `unsigned char` is more usually promoted to an `int` than an `unsigned int` so `%d` is likely to be the correct format specification in this case.
Charles Bailey
But `unsigned char` is promoted to `int` before the bitwise negation takes place. You'd have to cast back to `unsigned char` afterwards for it to work as desired.
R..
A: 

One (mildly humorous) way to think of signed maths is to recognize that the most significant bit really represents an infinite number of bits above it. So in a 16-bit signed number, the most significant bit is 32768+65536+131072+262144+...etc. which is 32768*(1+2+4+8+...) Using the standard formula for a power series, (1+ X + X^2 + X^3 +...) = 1/(1-X), one discovers that (1+2+4+8+...) is -1, so the sum of all those bits is -32768.

supercat