3

我知道 ~ 运算符不操作。但我无法弄清楚以下程序的输出(即-65536)。到底发生了什么?

#include <stdio.h>

int main(void) {
  int  b = 0xFFFF;
  printf("%d",~b);
  return 0;
}
4

7 回答 7

9

假设 32 位整数

int  b = 0xFFFF; => b = 0x0000FFFF
~b = 0xFFFF0000

现在设置了最高位。假设2s 补码,这意味着我们有一个负数。反转其他位然后加一个给出0x0001000065536

于 2013-07-30T16:34:18.933 回答
4

当您将 16 位值赋给0xffff32 位整数b时,变量b实际上变为0x0000ffff。这意味着当您进行按位补码时,它变成0xffff0000与 decimal 相同-65536

于 2013-07-30T16:33:24.973 回答
2

它正在做一个按位补码,这个输出可以帮助你更好地理解发生了什么:

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十进制。

在这种情况下,由于我们正在使用按位运算,因此检查十六进制数据可以让我们对正在发生的事情有所了解。

于 2013-07-30T16:33:59.760 回答
1

C++ 中的 ~ 运算符是按位 NOT 运算符。它也称为按位补码。这是翻转有符号整数的位。

例如,如果你有

 int b = 8;
 // b in binary = 1000
 // ~b = 0111

这将翻转表示提供的初始整数值的位。

于 2013-07-30T16:31:52.803 回答
1

结果取决于有符号整数在您的平台上的表示方式。最常见的表示是使用“2s 补码”算法来表示负值的 32 位值。也就是说,负值-x由与无符号值相同的位模式表示2^32 - x

在这种情况下,原始位模式设置了低 16 位:

0x0000ffff

按位取反清除这些位并设置高 16 位:

0xffff0000

将此解释为负数给出值-65536

通常,在处理按位算术时,您会希望使用无符号类型,以避免这种混淆。

于 2013-07-30T16:37:35.813 回答
0

你的评论:

如果它不是 '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。

于 2013-07-30T16:48:46.267 回答
-1

对于整数中的每个二进制数,按位 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

最高位是签名位(无论是正数还是负数),所以它给出一个负数。

于 2013-07-30T16:31:55.163 回答