需要对按位非 (~) 运算符进行说明
Posted
技术标签:
【中文标题】需要对按位非 (~) 运算符进行说明【英文标题】:Clarification is needed on bitwise not (~) operator 【发布时间】:2011-04-11 09:23:34 【问题描述】:假设您有以下 C 代码。
unsigned char a = 1;
printf("%d\n", ~a); // prints -2
printf("%d\n", a); // prints 1
我很惊讶地看到 -2 由于 ~1 转换而被打印出来:
0000 0001 的反义词是 1111 1110。这不是 -2。
我在这里错过了什么?
【问题讨论】:
将0和-1的值写入二进制。 "1111 1110 --> 除了 -2" 你从哪里得到这个?这正好是二进制补码的 -2。~
是一个位运算符,意味着它对数字的各个位进行运算; 二元运算符是接受两个操作数的运算符。
使用%u
进行无符号十进制转换。
【参考方案1】:
是补码。
在二进制补码表示中,如果数字 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。
【讨论】:
【参考方案2】:%d 代表有符号十进制数,而不是无符号数。因此,您的位模式,即使它存储在无符号变量中,也会被解释为有符号数。
请参阅此Wikipedia entry on signed number representations 以了解位值。具体见Two's complement。
【讨论】:
但是在对可变参数函数的调用中,unsigned char
通常被提升为int
而不是unsigned int
,因此%d
在这种情况下可能是正确的格式规范。
但是unsigned char
在按位取反发生之前被提升为int
。之后您必须转换回 unsigned char
才能使其按需要工作。【参考方案3】:
思考有符号数学的一种(略带幽默)方式是认识到最高有效位实际上代表了它上面的无限数量的位。所以在一个 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。
【讨论】:
以上是关于需要对按位非 (~) 运算符进行说明的主要内容,如果未能解决你的问题,请参考以下文章