假設您有以下C代碼。澄清需要按位不(〜)運算符
unsigned char a = 1;
printf("%d\n", ~a); // prints -2
printf("%d\n", a); // prints 1
我驚訝地發現-2印刷爲〜1個變換的結果:
的0000 0001相對的是1111 1110即是什麼,但-2。
我在這裏錯過了什麼?
假設您有以下C代碼。澄清需要按位不(〜)運算符
unsigned char a = 1;
printf("%d\n", ~a); // prints -2
printf("%d\n", a); // prints 1
我驚訝地發現-2印刷爲〜1個變換的結果:
的0000 0001相對的是1111 1110即是什麼,但-2。
我在這裏錯過了什麼?
它是二的補碼。在二進制補碼錶示中,如果數字x的最高有效位是1,那麼實際值將是−(〜x + 1)。
例如,
0b11110000 = -(~0b1111 + 1) = -(15 + 1) = -16.
這是負數的自然表示,因爲
0000001 = 1
0000000 = 0
1111111 = -1 (wrap around)
1111110 = -2
1111101 = -3 etc.
參見http://en.wikipedia.org/wiki/Two%27s_complement詳細。
順便說一句,爲了打印一個無符號的值,使用%hhu
或%hhx
格式。見http://www.ideone.com/YafE3。
%d代表有符號的十進制數,不是無符號的。所以你的位模式,即使它存儲在一個無符號變量中,也被解釋爲一個有符號數。
查看此Wikipedia entry on signed number representations瞭解位值。具體見Two's complement。
但是在調用可變參數函數時,'unsigned char'通常比'unsigned int'更容易提升爲'int',所以'%d'在這種情況下可能是正確的格式規範。 – 2010-09-12 18:40:24
但是,在發生按位否定之前,將'unsigned char'提升爲'int'。之後您必須重新轉換爲'unsigned char',以便按照需要工作。 – 2010-09-12 18:47:40
想到有符號數學的一種(輕度幽默)方法是認識到最重要的位實際上代表了無限多個位。所以在16位有符號數中,最高有效位是32768 + 65536 + 131072 + 262144 + ...等。 (1 + X + X^2 + X^3 + ...)= 1 /(1-X)是32768 *(1 + 2 + 4 + 8 + ...) ),發現(1 + 2 + 4 + 8 + ...)是-1,因此所有這些位的總和是-32768。
以二進制寫入0和-1的值。 – 2010-09-12 18:19:51
「1111 1110 - >除了-2之外的任何東西」你在哪裏得到這個?這完全是二進制補碼。 – recursive 2010-09-12 18:19:59
嘗試'print(「%x」)' – pmg 2010-09-12 18:22:37