azz*_*azz 11 java bit-manipulation
在Java中:
(0xFFFFFFFF << 1) = 0xFFFFFFFE = 0b1111111111111110
: : :
(0xFFFFFFFF << 30) = 0xE0000000 = 0b1110000000000000
(0xFFFFFFFF << 30) = 0xC0000000 = 0b1100000000000000
(0xFFFFFFFF << 31) = 0x80000000 = 0b1000000000000000
Run Code Online (Sandbox Code Playgroud)
然而:
(0xFFFFFFFF << 32) = 0xFFFFFFFF = 0b1111111111111111
Run Code Online (Sandbox Code Playgroud)
逻辑上这没有任何意义,但我认为发生的事情是Java执行类似于以下操作的操作:
a << (b % Integer.SIZE) [编辑,显然:] a << (b & 0x1F)
这也适用于>>和>>>,太.
显然,移位> = 32(在整数的情况下)会从数据类型中删除所有数据,但有时这很有用.例如:
int value = 0x3F43F466; // any value
int shift = 17; // any value >= 0
int carry = value & (-1 << (Integer.SIZE - shift));
if (carry > 0)
; // code...
Run Code Online (Sandbox Code Playgroud)
当然这可以修复,但找到这些错误可能非常耗时(我只花了几个小时跟踪类似的一个).所以,我的问题:是否有理由在将所有位移出时不返回逻辑值?
我在C99中尝试了这个,使用以下内容:
#include<stdio.h>
main()
{
int i, val;
for (i = 0; i <=36; i++) {
val = (-1 << i);
printf("%d :\t%d\n", i, val);
}
}
Run Code Online (Sandbox Code Playgroud)
我发现它的行为与Java相同,掩盖i & 0x1F,而在给定一个常量值时,它在编译时提供警告:
warning: left shift count >= width of type
Run Code Online (Sandbox Code Playgroud)
当然,有:大多数处理器(特别是包括x86)实现位移,并做你想要的 - 检查移位是否大于32,如果是,返回零 - 需要一个分支,这可以在现代CPU上很昂贵.这不仅仅是"令人讨厌",它可以减慢数量级的速度.
简而言之,执行您想要的操作会增加高性能代码预期会快速运行的操作.
作为参考,逻辑并不完全相同%,它是一个掩码.有关详细信息,请参阅JLS 15.19:
如果左侧操作数的提升类型是int,则只使用右侧操作数的五个最低位作为移位距离.就好像右手操作数受到按位逻辑AND运算符&(§15.22.1)和掩码值0x1f(0b11111)的影响.因此,实际使用的移位距离始终在0到31的范围内,包括0和31.
| 归档时间: |
|
| 查看次数: |
2709 次 |
| 最近记录: |