Java中的位移操作是否是循环的?

7

我使用Java时遇到了这个问题:

int b=16;
System.out.println(b<<30);
System.out.println(b<<31);
System.out.println(b<<32);
System.out.println(b<<33);

输出: 0 0 16 32

Java的位移操作是循环的吗?如果不是,为什么当b<<30时得到0,而当b<<32时得到16?

2个回答

13

位移操作不是循环操作。对于位移 int,Java只使用5个最低有效位,因此(b << 0)等同于(b << 32)(等同于(b << 64),以此类推)。你可以将位移量除以32并取余数。

对于位移 long,类似的情况发生,Java只使用6个最低有效位,因此(aLong << 0)等同于(aLong << 64)

JLS第15.19节讨论了这一点:

如果左操作数的提升类型为int,则仅使用右操作数的最低的五个有效位作为移位距离。就好像右操作数受到按位逻辑与运算符&(§15.22.1)的影响,掩码值为0x1f (0b11111)一样。因此实际使用的移位距离总在包括0和31的范围内。
如果左操作数的提升类型为long,则仅使用右操作数的最低的六个有效位作为移位距离。就好像右操作数受到按位逻辑与运算符&(§15.22.1)的影响,掩码值为0x3f (0b111111)一样。因此实际使用的移位距离总在包括0和63的范围内。
(强调是我加的)
(你不能对float或double进行位移操作,而尝试对short或byte进行位移将使该值受到一元数字推广到int的影响。)

当你执行 16 << 30 时,你会得到 0,因为 16 的二进制表示中只有一个位是1。

00000000 00000000 00000000 00010000

被移动到 int 的末尾并被丢弃。

// Discarded - Result-----------------------------
  (00000100)   00000000 00000000 00000000 00000000 

对于右移操作,是不是也只会影响右操作数的最低5位?谢谢! - dykw
正确的。我引用的JLS第一节涉及所有的移位运算符:<<>>>>> - rgettman

5
不,这不是循环移位,而是普通的左移位。对于int类型的左侧操作数,Java仅使用右操作数的5个低位进行移位。这符合JLS §15.9的规定:
如果左操作数的提升类型为int,则只使用右操作数的五个最低位作为移位距离。就像将右操作数 subjected to a bitwise logical AND operator & (§15.22.1) with the mask value 0x1f (0b11111)一样。因此实际使用的移位距离总是在0到31之间,包括0和31。
所以,对于16 << 32,仅考虑32的5个低位,该表达式相当于:
16 << 32 & 0x1f

这相当于16。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接