假设您有以下C代码。
unsigned char a = 1;
printf("%d\n", ~a); // prints -2
printf("%d\n", a); // prints 1
我很惊讶地发现 - 由于~1转换打印了-2:
<00>与0000 0001相反的是1111 1110.这不是-2。我在这里缺少什么?
答案 0 :(得分:10)
这是两个补充。
在二进制补码表示中,如果数字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。
答案 1 :(得分:4)
%d代表带符号的十进制数,而不是无符号。因此,即使存储在无符号变量中,您的位模式也会被解释为带符号的数字。
请参阅此Wikipedia entry on signed number representations以了解位值。特别参见Two's complement。
答案 2 :(得分:0)
考虑有符号数学的一种(温和的幽默)方法是认识到最重要的位实际上代表了它上面的无限位数。因此,在16位有符号数中,最高有效位是32768 + 65536 + 131072 + 262144 + ...等。这是32768 *(1 + 2 + 4 + 8 + ...)使用幂级数的标准公式,(1 + X + X ^ 2 + X ^ 3 + ...)= 1 /(1-X ),一个发现(1 + 2 + 4 + 8 + ...)是-1,所以这些位的总和是-32768。