我正在学习C语言。我有这个代码,如果需要可以提供更多代码:
int result = 0;
int mask1 = 0x0000ffff;
mask1 = mask1 >> 28;
当我使用gdb并打印/x mask1
时,我得到0x0
,这是正确的。
那为什么:
int result = 0;
int mask1 = 0xffffffff;
mask1 = mask1 >> 28;
print 0xffffffff
不应该打印0x0000000f
,因为我要移位28位?
是否与我的64位机器上占用的int位数有关? 我看了this,但它并没有完全回答所有问题。
答案 0 :(得分:5)
负整数右移的行为是实现定义的。一种常见的行为是算术移位,它进行符号扩展。这样做的好处是右移也可以除以2的幂(舍入到负无穷大),就像正数一样。
答案 1 :(得分:1)
您正在正确。这是正确的:>>
,现在留下:<<
。
通常,当你正确地移动一个(带符号)整数时,你会假设你正在改变值而不是符号:这就是Daniel的意思通过签名扩展。标准并不要求它,并非所有平台都这样做。
实际上,在使用二进制补码的系统上,这意味着负值会使新的顶部位填充1
,而正值会填充0
。
例如,在8位2s补码系统上:
before after >> 1
11111110 = -2 11111111 = -1 (so new top bit was 1)
00000010 = +2 00000001 = +1 (so new top bit was 0)
答案 2 :(得分:0)
如果您将0xffffffff打印为整数,您将意识到它被视为-1。
Bitshift与负数的工作方式不同,因为它用1填充最高位。所以基本上,0xffffffff&gt;&gt; 1 == 0xffffffff。
如果您将面具声明为unsigned int
,那么它可能会执行您想要的操作。
答案 3 :(得分:0)
负整数的按位右移是实现定义的。
以下是gcc
的作用:
对有符号整数进行一些按位运算的结果(C90 6.3,C99 6.5)。
签名`&gt;&gt;'通过符号扩展对负数进行处理。
http://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html
答案 4 :(得分:0)
是的,正如@veer指出的那样,int
你正在做一个正确的算术移位,这对于将有符号数除以2的幂(以二进制补码表示)是很好的:
通过将类型更改为unsigned int
,它将成为右向位移,非常适合将无符号数除以2的幂(这是您的方案):
关于Wikipedia Bitwise operation的一些很好的解释。