Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/393.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
不需要的Java位移位行为_Java_Bit Shift - Fatal编程技术网

不需要的Java位移位行为

不需要的Java位移位行为,java,bit-shift,Java,Bit Shift,我正在为我正在做的一些计算生成位掩码,我需要掩码一个int,这样除了x最右边的位之外,所有的位都变成零。我使用以下方法进行此操作: int mask = ~(-1 << x); 当x=0时,它应该返回0,但它返回-1。不知何故,将某物移动32会导致操作返回操作员的左侧。当我尝试将-1移位33位或34位时,它返回一个值,就好像它移位了1位或2位一样。我是否正确地假设Java实际上做了这样的事情: int mask = ~(-1 << x % 32); ? 如果是这样的话

我正在为我正在做的一些计算生成位掩码,我需要掩码一个int,这样除了x最右边的位之外,所有的位都变成零。我使用以下方法进行此操作:

int mask = ~(-1 << x);
当x=0时,它应该返回0,但它返回-1。不知何故,将某物移动32会导致操作返回操作员的左侧。当我尝试将-1移位33位或34位时,它返回一个值,就好像它移位了1位或2位一样。我是否正确地假设Java实际上做了这样的事情:

int mask = ~(-1 << x % 32);
?

如果是这样的话,如果超过int的32位长度,为什么要使用这种循环行为?关于Oracle的文档明确指出:

无符号右移运算符“>>>”将零移到 最左边的位置


但很明显,当它必须移动超过32时,它实际上并没有这样做…

是的,你是对的;在应用移位之前,移位调整32(或64,对于
long
s)

:

如果左侧操作数的提升类型为int,则仅将右侧操作数的五个最低阶位用作移位距离。这就好像右侧操作数接受了位逻辑AND运算符(§15.22.1),掩码值为0x1f(0b11111)。因此,实际使用的移动距离始终在0到31之间(包括0到31)

如果左侧操作数的提升类型为长,则仅将右侧操作数的六个最低阶位用作移位距离。这就好像右侧操作数接受了位逻辑AND运算符(§15.22.1),掩码值为0x3f(0b111111)。因此,实际使用的移动距离始终在0到63之间(包括0到63)


至于Java为什么选择这种行为,我没有任何建议。

好的,谢谢你的快速回答,但是为什么?根据数据类型的大小对mod进行额外工作的原因是什么?对于等于或大于数据类型大小的移位,为什么不直接返回0?是否有一个经常使用的用例来证明这种行为的合理性?嗯,也许现在你已经展示了它只是屏蔽了操作符的右侧,这样做可能比检查移位是否大于32更快,如果是,则返回0(我想要的行为),导致任何其他移位,特别是int的最大值,如果非要我猜的话,可能要花很长时间来计算?我要说的是,在这种特殊情况下,硬件转移具有不同的行为,这种实现在几乎所有处理器上都是无分支的,而另一种方法则需要在大多数人期望的快速操作上进行分支。我还怀疑,固定距离的移位比另一种更为常见。
int mask = ~(-1 << x % 32);
int mask = -1 >>> (32 - x) % 32;