Reputation: 1807
I'm generating bitmasks for some calculations I'm doing, where I need to mask an int such that all except the x rightmost bits become zero. I do this using:
int mask = ~(-1 << x);
This works fine for all values of x except for x = 32. It should return -1 then, but it returns 0. What is happening here?
Also, I tried this:
int mask = -1 >>> 32 - x;
At x = 0 it should return 0, yet it returns -1. Somehow shifting something by 32 causes the operation to return the left side of the operator. When I try shifting -1 by 33 or 34 bits it returns a value as if it shifted by 1 or 2. Am I correct in assuming Java actually does something like this:
int mask = ~(-1 << x % 32);
and
int mask = -1 >>> (32 - x) % 32;
?
If so, why would you want this loop around behavior if you go above the 32 bit length of the int? The documentation on Oracle clearly states:
The unsigned right shift operator ">>>" shifts a zero into the leftmost position
But clearly that's not actually what it's doing when it has to shift by more than 32...
Upvotes: 3
Views: 1599
Reputation: 198014
Yes, you're correct; shifts are modded by 32 (or 64, for long
s) before they're applied.
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 value 0x1f (0b11111). The shift distance actually used is therefore always in the range 0 to 31, inclusive.
If the promoted type of the left-hand operand is long, then only the six 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 value 0x3f (0b111111). The shift distance actually used is therefore always in the range 0 to 63, inclusive.
As to why Java chose this behavior, I don't have any advice for you.
Upvotes: 8