为什么位移位位移字节会根据移位顺序产生不同的值?

时间:2015-10-19 16:39:50

标签: java casting bit-manipulation byte bit-shift

考虑这个Java代码:

    byte a = (byte) 0b01111110; //Binary Literal
    byte b1 = (byte) (a << 1);
    byte c1 = (byte) (a >> 1);
    byte b2 = (byte) (b1 >> 1);
    byte c2 = (byte) (c1 << 1);
    System.out.println("A:" + a + " B1:" + b1 + " C1:" + c1 + " B2:" + b2 + " C2:" + c2);

结果输出为:

A:126 B1:-4 C1:63 B2:-2 C2:126

为什么字节&#39; b2&#39;有一个不等于&#39; a&#39;的值。 (以及&#39; c2&#39;在这种情况下)即使两个班次都没有导致二进制数字被删除?

2 个答案:

答案 0 :(得分:4)

因为符号扩展。使用>>>来阻止:

byte a = (byte) 0b01111110; // 0b01111110 = 126
byte b1 = (byte) (a << 1);  // 0b11111100 =  -4  <-- overflow
byte c1 = (byte) (a >> 1);  // 0b00111111 =  63
byte b2 = (byte) (b1 >> 1); // 0b11111110 =  -2  <-- sign extension
byte c2 = (byte) (c1 << 1); // 0b01111110 = 126

byte x = (byte) (b1 >>> 1); // 0b01111110 = 126  <-- no sign extension

此外,您的陈述“即使两个班次都没有导致二进制数字被删除”也是不正确的。所有班次操作删除一个数字。在你的情况下,丢弃的数字恰好为零。

答案 1 :(得分:-1)

  

...两个班次都没有导致二进制数字被删除

假。

所有班次操作都会导致数字被删除。通过愚蠢的运气,你所观察到的只是反驳了这一点,因为0位被删除了。我认为您的问题必须与sign extensions一致,并理解算术转换>><<,与逻辑转变({ {1}})。执行算术移位时,会扩展符号位以保留数字的签名。

引用Java的official documentation

  

签名的左移运营商&#34;&lt;&lt;&#;将位模式向左移动,   和签名的右移操作员&#34;&gt;&gt;&#34;将位模式转换为   对。位模式由左侧操作数和   由右手操作数移动的仓位数。未签名的   右移运算符&#34;&gt;&gt;&gt;&#34;将零移动到最左边的位置,   而在&#34;&gt;&gt;&#34;之后的最左边的位置取决于符号扩展。