[英]Java bitshift strangeness
Java有兩個用於右移的位移操作符:
>> shifts right, and is dependant on the sign bit for the sign of the result
>>> shifts right and shifts a zero into leftmost bits
http://java.sun.com/docs/books/tutorial/java/nutsandbolts/op3.html
這看起來相當簡單,所以任何人都可以向我解釋為什么這個代碼,當bar為-128的值時,為foo產生-2的值:
byte foo = (byte)((bar & ((byte)-64)) >>> 6);
這意味着要做一個8位字節,最左邊2位的掩碼,並將它們移到最右邊的2位。 即:
initial = 0b10000000 (-128)
-64 = 0b11000000
initial & -64 = 0b10000000
0b10000000 >>> 6 = 0b00000010
結果實際上是-2,即
0b11111110
IE瀏覽器。 1s而不是零被移動到左側位置
這是因為&實際上正在對int
進行升級 - 這留下了大量的“1”位。 然后你向右移動,將最左邊的2位保留為0,然后通過轉回字節忽略那些最左邊的位。
當你將操作分開時,這會變得更清晰:
public class Test
{
public static void main(String[] args)
{
byte bar = -128;
int tmp = (bar & ((byte)-64)) >>> 6;
byte foo = (byte)tmp;
System.out.println(tmp);
System.out.println(foo);
}
}
版畫
67108862
-2
所以再做一點算術:
initial = 0b10000000 (-128)
-64 = 0b11000000
initial & -64 = 0b11111111111111111111111110000000 // it's an int now
0b10000000 >>> 6 = 0b00111111111111111111111111100000 // note zero-padding
(byte) (0b10000000 >>> 6) = 11100000 // -2
即使你從&操作中獲得了正確的結果(通過在該點進行轉換), >>>
也會首先將第一個操作數提升為int
。
編輯:解決方案是改變你掩蓋事物的方式。 而不是掩蓋-64,而是掩蓋僅128 + 64 = 192 = 0xc0:
byte foo = (byte)((bar & 0xc0) >>> 6);
這樣你真的只剩下你想要的兩個位,而不是在最重要的24位中加載1。
AFAIK,在Java中大多數運算符(+, - ,>>等等)都不能處理小於int
的任何東西。 所以,你的按位移位和&
隱式地將值轉換為背景中的int
,然后通過外部顯式轉換返回到byte
。 最后一次轉換消除了較高位中的零。
要獲得您期望的結果,請嘗試在int
上執行此操作。
其他人告訴你為什么,但我會進一步分解並提供真正問題的答案。
byte foo = (byte)((bar & ((byte)-64)) >>> 6);
由於&運算符會將所有內容提升為int,因此它的作用基本上是:
byte foo = (byte)(((int)bar & (int)((byte)-64)) >>> 6);
如果bar是-128那么(int)bar是0xFFFFFF80然后用0xFFFFFFC0編輯...這是:0xFFFFFF80,然后你向右移動6位得到:0x3FFFFFFE
正確的答案很簡單:
byte foo = (byte)((bar & 0xC0) >> 6);
bar被提升為&操作的int,因此int中唯一剩下的就是原始字節的前兩位。 然后將其右移6位並將其轉換回字節。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.