11

在 Java 中:

(0xFFFFFFFF <<  1) = 0xFFFFFFFE = 0b1111111111111110
                :         :               :
(0xFFFFFFFF << 30) = 0xE0000000 = 0b1110000000000000
(0xFFFFFFFF << 30) = 0xC0000000 = 0b1100000000000000
(0xFFFFFFFF << 31) = 0x80000000 = 0b1000000000000000

然而:

(0xFFFFFFFF << 32) = 0xFFFFFFFF = 0b1111111111111111

从逻辑上讲,这没有任何意义,但我相信正在发生的是 Java 执行类似于:

a << (b % Integer.SIZE)[编辑,显然:]a << (b & 0x1F)

这也适用于>>and >>>

显然,移动 >= 32(在整数的情况下)会从数据类型中删除所有数据,但有时这很有用。例如:

int value = 0x3F43F466; // any value
int shift = 17; // any value >= 0
int carry = value & (-1 << (Integer.SIZE - shift));
if (carry > 0)
    ; // code...

当然,这可以修复,但发现这些错误可能非常耗时(我只花了几个小时跟踪一个类似的错误)。所以,我的问题是:将所有位移出时是否有理由不返回逻辑值?

更新:

我在 C99 中尝试过,使用以下内容:

#include<stdio.h>
main()
{
   int i, val;
   for (i = 0; i <=36; i++) {
       val = (-1 << i);
       printf("%d :\t%d\n", i, val);
   }
}

我发现它的行为与 Java 相同, masking i & 0x1F,而当给定一个常量值时,它会在编译时提供警告:

warning: left shift count >= width of type
4

2 回答 2

8

当然,有:这是大多数处理器(特别是 x86)实现位移的方式,并做你想做的事——检查位移是否大于 32,如果是,则返回零——需要一个分支,它可以在现代 CPU 上价格昂贵。这不仅仅是“烦人”,它可以使事情变慢几个数量级。

简而言之,做你想做的事情会给一个预计会因高性能代码而快速运行的操作增加大量开销。

作为参考,逻辑与 不完全相同%,它是一个掩码。有关详细信息,请参阅JLS 15.19

If the promoted type of the left-hand operand is int, only the five lowest-order bits of the right-hand operand are used as the shift distance. It is as if the right-hand operand were subjected to a bitwise logical AND operator & (§15.22.1) with the mask value 0x1f (0b11111). The shift distance actually used is therefore always in the range 0 to 31, inclusive.

于 2013-03-29T18:06:30.397 回答
4

JLS 15.19 If the promoted type of the left-hand operand is int, only the five lowest-order bits of the right-hand operand are used as the shift distance. It is as if the right-hand operand were subjected to a bitwise logical AND operator & (§15.22.1) with the mask value 0x1f (0b11111). The shift distance actually used is therefore always in the range 0 to 31, inclusive

to put it simply 0xFFFFFFFF << 32 is equivalnt to 0xFFFFFFFF << (32 & 0x1f) is equivalent to 0xFFFFFFFF << 0

于 2013-03-29T18:09:05.920 回答