Java整数左移的奇怪结果

Weird result of Java Integer left shift

我现在对java左移操作有点困惑,

1<<31 =  0x80000000  --> this I can understand

但是

1<<32 =  1       Why is this?
1<<33 =  2       

看起来像更多的移位值,取值的模数 32。

感谢大家的回复和JLS的引用

我只是想知道更多。知道以这种方式设计的原因吗?还是只是一些惯例?显然 C 没有这个怪癖?

Thanks to @paxdiablo. Looks like C declares this behaviour undefined.

这里有一些个人的假设:

ARM architecture Reference Manual A7.1.38

Syntax LSL Rd, Rm, #immed_5

where:

Rd Is the register that stores the result of the operation.

Rm Is the register containing the value to be shifted.

immed_5 Specifies the shift amount, in the range 0 to 31.

在指令层面,立即数immed_5只占用5位,避免无意义的操作,从而节省一些指令space。我想高级语言只是统一了这个约定,以避免在编译为指令时进行无意义的工作。

根据 Java 语言规范 15.19. Shift Operators(略有释义):

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 & with the mask value 0x1f ,or 0b11111. The shift distance actually used is therefore always in the range 0 to 31, inclusive.

这意味着(例如)33,作为 6 位二进制 100001,在使用之前被缩减为 5 位 00001。所以 x << 33 等同于 x << 1.

System.out.println(Integer.toBinaryString(1 << 32)); 

将二进制 1(10) 向左移动 32 次。因此:十进制为 1

System.out.println(Integer.toBinaryString(1 << 33)); 

现在,int 是 4 个字节,因此是 32 位。所以当你移动 33 时,它相当于移动 1。因此: 2 in decimal