Java奇异程序输出中的Shift运算符

我遇到了以下程序,它表现得出乎意料。

public class ShiftProgram { public static void main(String[] args) { int i = 0; while(-1 << i != 0) i++; System.out.println(i); } } 

如果我们考虑这个程序输出,当它达到32时,循环条件应该返回false并终止,它应该打印32。

如果你运行这个程序,它不会打印任何东西,但会进入无限循环。 有什么想法吗? 先谢谢你。

您是否尝试在循环中打印出(-1 << i)以查看出现了什么问题? 如果你这样做,你会看到它:

 -1 << 0 = -1 -1 << 1 = -2 -1 << 2 = -4 -1 << 3 = -8 -1 << 4 = -16 -1 << 5 = -32 -1 << 6 = -64 -1 << 7 = -128 -1 << 8 = -256 -1 << 9 = -512 -1 << 10 = -1024 -1 << 11 = -2048 -1 << 12 = -4096 -1 << 13 = -8192 -1 << 14 = -16384 -1 << 15 = -32768 -1 << 16 = -65536 -1 << 17 = -131072 -1 << 18 = -262144 -1 << 19 = -524288 -1 << 20 = -1048576 -1 << 21 = -2097152 -1 << 22 = -4194304 -1 << 23 = -8388608 -1 << 24 = -16777216 -1 << 25 = -33554432 -1 << 26 = -67108864 -1 << 27 = -134217728 -1 << 28 = -268435456 -1 << 29 = -536870912 -1 << 30 = -1073741824 -1 << 31 = -2147483648 -1 << 32 = -1 -1 << 33 = -2 -1 << 34 = -4 -1 << 35 = -8 -1 << 36 = -16 [.. etc ..] 

根据语言规范 :

n << s的值是n个左移位s位; 这相当于(即使发生溢出)与功率s相乘2。

......所以结果总是保持负面。

那份文件还告诉你:

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

因此,如果使用32的移位,则将其解释为32 & 0x1f的移位,即0-1偏移0仍然只是-1 ,而不是0

移位计数以int (32)中的位数为模来解释,因此i << 32只是i << 0 ,即i 。 因此,结果永远不会得到0 。 我的来源是http://www.janeg.ca/scjp/oper/shift.html 。 如果你做int n = -1; while (n != 0) {i++; n <<= 1;}类的事情int n = -1; while (n != 0) {i++; n <<= 1;} int n = -1; while (n != 0) {i++; n <<= 1;} int n = -1; while (n != 0) {i++; n <<= 1;} ,它最终会达到你想要的0