The shift operators in Java have the following properties, according to The Java Language Specification (JLS), §15.19, "Shift Operators" [JLS 20052015]:
- The
>>
right shift is an arithmetic shift; the>>>
right shift is a logical shift. - The types
boolean
,float
, anddouble
cannot use the bit-shifting operators. - When the value to be shifted is of type
int
, only the five lowest-order bits of the right-hand operand are used as the shift distance. That is, the shift distance is the value of the right-hand operand masked by 31 (0x1F). The shift distance actually used is consequently always in the range 0 to 31, inclusive. - When the value to be shifted (left operand) is type
long
, only the last 6 bits of the right-hand operand are used to perform the shift. The shift distance is the value of the right-hand operand masked by 63 (0x3F). The shift distance actually used is consequently always in the range 0 to 63, inclusive.
...
Arithmetic vs. Logical Shift
The JLS, §15.19 [JLS 20052015], defines the behavior of the arithmetic shift operator as follows:
The value of n>>s n>>s is n right-shifted s bit positions with sign-extension. The resulting value is ⌊ floor(n / 2s ⌋). For nonnegative values of n, this is equivalent to truncating integer division, as computed by the integer division operator /, by two to the power s.
The JLS also defines the behavior of the logical shift operator:
The value of n>>>s n >>> s is n right-shifted s bit positions with zero-extension, where:
• . If n is positive, then the result is the same as that of n>>s; if n >> s.
• If n is negative and the type of the left-hand operand is int, then the result is equal to that of the expression (n>>sn >> s) + (2<<~s) if 2 << ~s).
• If n is negative and the type of the left-hand operand is intlong, and to then the result is equal to that of the expression (n>>sn >> s) + (2L<<~s) if the type of the left-hand operand is long. 2L << ~s).
The added term (2<<~s2 << ~s) or (2L<<~s2L << ~s) cancels out the propagated sign bit.
(Note that, because of the implicit masking of the right-hand operand of a shift operator, ~s ~s as a shift distance is equivalent to 31-s when shifting an
int
value and to 63-s when shifting along
value.)
Never use the arithmetic shift operator when the logical shift operator is required.
...
Code Block | ||
---|---|---|
| ||
static int countOneBits(long value) { int bits = 0; while (value != 0) { bits += value & 1L; value >>= 1; // Signed right- shift, by one } return bits; } |
...
In this noncompliant code example, the programmer intends to shift a byte value two bits to the right (with zero fill). However, the JLS specifies that the left operand must be promoted to either type int
or type long
(int
, in this case); this promotion performs sign extension. Because of the promotion, the result of the shift for negative input values will be a large positive number, and the programmer could find this result surprising.
Code Block | ||
---|---|---|
| ||
byte b = /* Initialize */; int result = b >>> 2; |
...
This noncompliant code example tries to shift the value -1
by increasing the value of i
until, after 32 iterations, the programmer believes the result would become 0. The loop actually never terminates because an attempt to shift a value of type int
by 32 bits results in the original value (that is, −1) rather than the expected value 0 [Bloch 2005] . This is because only the least significant 5 bits of i
are considered when the shift occurs, and when i
reaches the value 32, the 5 least significant bits have the value 0.
...
Incorrect use of shift operators can lead to unanticipated results, causing erratic control flow or unanticipated program behavior.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
NUM14-J | Low | Probable | Medium | P4 | L3 |
Automated Detection
...
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
PVS-Studio |
| V6034 |
Related Guidelines
Bibliography
...
...