java比特移位循环吗?

dyk*_*ykw 5 java bit-manipulation bit-shift

我有使用Java的这种行为:

int b=16;
System.out.println(b<<30);
System.out.println(b<<31);
System.out.println(b<<32);
System.out.println(b<<33);
Run Code Online (Sandbox Code Playgroud)

输出:0 0 16 32

java位移位循环吗?如果没有,为什么我在b << 30和16时b <32时得到0?

rge*_*man 12

位移不是循环的; 对于位移ints,Java仅使用5个最低有效位,因此(b << 0)相当于(b << 32)(相当于(b << 64)等).您可以简单地取位移量并在除以32时取余数.

对于位移longs 也会出现类似情况,其中Java仅使用6个最低有效位,因此(aLong << 0)相当于(aLong << 64).

JLS第15.19节谈到了这一点:

如果左侧操作数的提升类型是int,则只使用右侧操作数的五个最低位作为移位距离.就好像右手操作数受到按位逻辑AND运算符&(§15.22.1)和掩码值0x1f(0b11111)的影响.因此,实际使用的移位距离始终在0到31的范围内,包括0和31.

如果左侧操作数的提升类型很长,则只使用右侧操作数的六个最低位作为移位距离.就好像右手操作数受到按位逻辑AND运算符&(§15.22.1)和掩码值0x3f(0b111111)的影响.因此,实际使用的移位距离始终在0到63的范围内,包括0和63.

(强调我的)

(你不能对floats或doubles进行比特移位,并且尝试按比例移位a short或者a byte会使值一直受到一元数字提升的影响int.)

0来自16 << 30,因为1位来自16

00000000 00000000 00000000 00010000
Run Code Online (Sandbox Code Playgroud)

从最后移开int并被丢弃.

// Discarded - Result-----------------------------
  (00000100)   00000000 00000000 00000000 00000000 
Run Code Online (Sandbox Code Playgroud)


Roh*_*ain 5

不,这不是循环转变.这是正常的左移.只是,对于int类型左侧操作数,Java仅使用右操作数的5个低位来进行移位.这符合JLS§15.9:

如果左侧操作数的提升类型是int,则只使用右侧操作数的五个最低位作为移位距离.就好像右手操作数受到按位逻辑AND运算符&(§15.22.1)和掩码值0x1f(0b11111)的影响.因此,实际使用的移位距离始终在0到31的范围内,包括0和31

因此,对于16 << 32仅考虑5个低阶位32,表达式相当于:

16 << 32 & 0x1f
Run Code Online (Sandbox Code Playgroud)

等于16.