Why if
int x = -1 // binary: 11111111111111111111111111111111
x = x >>> 31;
we have 00000000000000000000000000000001
but if
int x = -1
x = x >>> 32;
we have 11111111111111111111111111111111 (again -1)
but not 00000000000000000000000000000000 ?
From Section 15.19 of JLS:
If the promoted type of the left-hand operand is int, only the five lowest-order bits of the right-hand operand are used as the shift distance. It is as if the right-hand operand were subjected to a bitwise logical AND operator
&
(§15.22.1) with the mask value0x1f (0b11111)
. The shift distance actually used is therefore always in the range0 to 31
, inclusive.
Emphasis mine. So:
x >>> n
is equivalent to:
x >>> n & 0x1f // or x >>> n % 32
So, x >>> 32
is equivalent to x >>> 32 & 0x1f
<==> x >>> 0
== x
.
So the Rule of Thumb is, whenever you shift a number by a multiple of 32
(int
is 32 bits
), you get back the same value.
When applying the bit-shift operation only the lowest 5 bits of the right-hand operand are considered. Since 32 === 0 // mod 32, the result is no shifting.
Spent an entire day breaking my head over why a long l = i << 32 behaved strangely, then wrote some basic tests, had the WTF moment, and then chnged to long l = (long) i << 32 for it to work.
My only add to Rohit's answer is the reason why this is so. From IA-32 Intel Architecture Software Developer’s Manual 3:
The 8086 does not mask the shift count. However, all other IA-32 processors (starting with the Intel 286 processor) do mask the shift count to 5 bits, resulting in a maximum count of 31. This masking is done in all operating modes (including the virtual-8086 mode) to reduce the maximum execution time of the instructions
来源:https://stackoverflow.com/questions/14817639/java-bit-operations-shift