Software Engineering for Smart Data Analytics & Smart Data Analytics for Software Engineering
The italic text indicates what you should do to fill in the template.
“The code performs shift of a 32 bit int by a constant amount outside the range -31..31. The effect of this is to use the lower 5 bits of the integer value to decide how much to shift by (e.g., shifting by 40 bits is the same as shifting by 8 bits, and shifting by 32 bits is the same as shifting by zero bits). This probably isn't what was expected, and it is at least confusing. ” – 2013-10-13
Java offers three kind of bit shift operators: > >, < <, > > > (signed right shift, signed left shift and unsigned right shift). These operators can be applied to a 32bit Integer to shift it by a constant in the preferred direction. The problem is that in Java the constant is processed before shifting. To the absolute value the modulo 32 operation is applied. This might be quite confusing since it leads to different shifting offsets than intended. e.g. shifting by 32 equals 32%32=0 and by 40 equals 40%32=8.
The background is that every Integer value is represented by a bit pattern which corresponds to the binary representation of the int value. The leftmost (highest) bit of a (signed) Integer is the sign. 0 means plus and 1 minus. The lowest bit corresponds to 2^0 and the 31st bit to 2^31. Hence the (signed) 32bit Integer has a range of [-2^31, 2^31-1]. If the sign is minus, the stored absolute value equals the complement (inverted bits) plus 1. By shifting to the left or right we simply move the bit pattern. > > and < < take the sign into account by filling up the pattern appropriately, while > > > doesn't.
Overview: example 1110 (-2 as a signed 4bit Integer)
1110 < < 1 is 1100 (-4 as a signed 4bit Integer)
1110 > > 1 is 1111 (-1 as a signed 4bit Integer)
1110 > > > 1 is 0111 (7 as a signed 4bit Integer)
<code Java> class ICAST_BAD_SHIFT_AMOUNT {
public static void main(String[] args){ int val = -8; System.out.println("We left shift "+val+" by 32: "+(val<<32)); }
} </Code>
First solution by making the hidden modulo operation visible
<code Java>
class ICAST_BAD_SHIFT_AMOUNT {
public static void main(String[] args){ int val = -8; System.out.println("We left shift "+val+" by 32: "+(val<<0)); // replaced by const%32 }
}
</Code>
Second solution by changing the range of the value, taking into account that the programmer might have expected the shifted variable to have a bigger range.
<code Java>
class ICAST_BAD_SHIFT_AMOUNT {
public static void main(String[] args){ long val = -8;//changed to long, if the programmer was expecting a bigger range System.out.println("We left shift "+val+" by 32: "+(val<<32)); }
}
</Code>
Benchmark project | Precision | Recall | ||||
---|---|---|---|---|---|---|
FB | JT | Delta | FB | JT | Delta | |
Project … | …% | …% | …% | …% | …% | …% |
Project … | …% | …% | …% | …% | …% | …% |
FB = FindBugs, JT = JTransformer, Delta = JTransformer - FindBugs