这是对负数的按位运算:
#include <stdio.h>
main()
{
int a = -20, b = 84;
printf("%d", (a>>(a &b)));
}
-20 的二进制补码是1100
二进制,而 84 是10000100
. a & b
应该是,100
但答案是 68,总体答案是 -2。
谁可以给我解释一下这个?
这是对负数的按位运算:
#include <stdio.h>
main()
{
int a = -20, b = 84;
printf("%d", (a>>(a &b)));
}
-20 的二进制补码是1100
二进制,而 84 是10000100
. a & b
应该是,100
但答案是 68,总体答案是 -2。
谁可以给我解释一下这个?
-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)
如果您使用的是 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