-4

这是对负数的按位运算:

#include <stdio.h>

main()
{
    int a = -20, b = 84;
    printf("%d", (a>>(a &b)));
}

-20 的二进制补码是1100二进制,而 84 是10000100. a & b应该是,100但答案是 68,总体答案是 -2。

谁可以给我解释一下这个?

4

2 回答 2

5

-20 不是 1100 2。最有可能(如果整数是 32 位并且我们不是在谈论奇数平台), 11111111111111111111111111101100 2

84 不是 10000100 2。它是 1010100 2

将它们与在一起:

11111111111111111111111111101100
&
00000000000000000000000001010100
=
00000000000000000000000001000100 (68 decimal)

然后你将 -20 向右移动 68 个位置,这有两个问题:

  • 负整数的右移是实现定义的,你的编译器的实现是什么?
  • 移位值中的位数或超过该位数会导致未定义的行为

128 位整数在常见平台上不太可能。64 位整数很少见,但并非不可能,但对他们来说 68 >= 64 ,所以你应该得到未定义的行为。

现在,这种未定义的行为可能是什么样子......

如果我们的 int 是 32 位的,并且我们在 x86 平台上执行此操作(或类似的平台),CPU 应该将 68 截断为 5 位,从而使移位计数为 68 和 31 = 4。

然后,假设SAR指令(保留符号的算术右移)用于>>,我们得到 (-20) SAR 4 = -2:

11111111111111111111111111101100
SAR
4
=
11111111111111111111111111111110 (-2 decimal)
于 2013-04-20T17:14:35.403 回答
3

如果您使用的是 Windows,它应该带有一个支持二进制的计算器应用程序。这是一个很好的可靠计算来源。你可以选择Word哪个是int。

左侧的所有位都是 1,因此在内存中记录了负数。所以 -20 是

  1111-1111-1110-1100
= 0xFFEC

84 是:

  0000-0000-0101-0100
= 0x0054

And 是一个按位运算,比较两个通过的数字,检查每个位。如果两个位都为 1,则结果位为 1。否则为 0。所以

  1111-1111-1110-1100
& 0000-0000-0101-0100
= 0000-0000-0100-0100
= 68
于 2013-04-20T17:13:23.183 回答