我知道 ~ 运算符不操作。但我无法弄清楚以下程序的输出(即-65536)。到底发生了什么?
#include <stdio.h>
int main(void) {
int b = 0xFFFF;
printf("%d",~b);
return 0;
}
我知道 ~ 运算符不操作。但我无法弄清楚以下程序的输出(即-65536)。到底发生了什么?
#include <stdio.h>
int main(void) {
int b = 0xFFFF;
printf("%d",~b);
return 0;
}
假设 32 位整数
int b = 0xFFFF; => b = 0x0000FFFF
~b = 0xFFFF0000
现在设置了最高位。假设2s 补码,这意味着我们有一个负数。反转其他位然后加一个给出0x00010000
或65536
当您将 16 位值赋给0xffff
32 位整数b
时,变量b
实际上变为0x0000ffff
。这意味着当您进行按位补码时,它变成0xffff0000
与 decimal 相同-65536
。
它正在做一个按位补码,这个输出可以帮助你更好地理解发生了什么:
std::cout << std::hex << " b: " << std::setfill('0') << std::setw(8) << b
<< " ~b: " << (~b) << " -65536: " << -65536 << std::endl ;
我收到的结果如下:
b: 0000ffff ~b: ffff0000 -65536: ffff0000
所以我们设置低 16 位1
给我们0000ffff
,然后我们做一个补码,这将设置低 16 位0
和高 16 位1
给我们ffff0000
,它等于-65536
十进制。
在这种情况下,由于我们正在使用按位运算,因此检查十六进制数据可以让我们对正在发生的事情有所了解。
C++ 中的 ~ 运算符是按位 NOT 运算符。它也称为按位补码。这是翻转有符号整数的位。
例如,如果你有
int b = 8;
// b in binary = 1000
// ~b = 0111
这将翻转表示提供的初始整数值的位。
结果取决于有符号整数在您的平台上的表示方式。最常见的表示是使用“2s 补码”算法来表示负值的 32 位值。也就是说,负值-x
由与无符号值相同的位模式表示2^32 - x
。
在这种情况下,原始位模式设置了低 16 位:
0x0000ffff
按位取反清除这些位并设置高 16 位:
0xffff0000
将此解释为负数给出值-65536
。
通常,在处理按位算术时,您会希望使用无符号类型,以避免这种混淆。
你的评论:
如果它不是 'b' .. 那么输出应该是 0 但为什么 -65536
建议您期待以下结果:
uint32_t x = 0xFFFF;
uint32_t y = ~x;
成为0
。
这对于逻辑非运算是正确的,例如:
uint32_t x = 0xFFFF;
uint32_t y = !x;
...但operator~
不是逻辑非,而是按位非。有一个很大的不同。
逻辑返回 0 表示非 0 值(或 false 表示真值),返回 1 表示 0 值。
但是按位不会反转给定值中的每个位。所以二进制 NOT 0xF
:
0x0F: 00000000 11111111
~0x0F: 11111111 00000000
不是零,而是 0xF0。
对于整数中的每个二进制数,按位 NOT 运算将所有 1 变为 0,并将所有 0 变为 1。
所以十六进制0xFFFF
是二进制1111 1111 1111 1111
(每个十六进制字符是 4 位,而 F 为 15,四位全为 1)
您为此设置了一个 32 位整数,这意味着它现在是:
0000 0000 0000 0000 1111 1111 1111 1111
然后你不是它,这意味着它是:
1111 1111 1111 1111 0000 0000 0000 0000
最高位是签名位(无论是正数还是负数),所以它给出一个负数。