需要对按位非 (~) 运算符进行说明

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。

【讨论】:

以上是关于需要对按位非 (~) 运算符进行说明的主要内容,如果未能解决你的问题,请参考以下文章

按位非运算符

按位非运算符的解释

JS按位非(~)运算符与~~运算符的理解分析

JS按位非(~)运算符与~~运算符的理解分析

python-opencv-图像的按位运算

05 Python运算符