假设您有以下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