3.14 Shift Operators: <<, >>, >>>

The binary shift operators form a new value by shifting bits either left or right a specified number of times in a given integral value. The number of shifts (also called the shift distance) is given by the right-hand operand, and the value that is to be shifted is given by the left-hand operand. Note that unary numeric promotion is applied to each operand individually. The value returned has the promoted type of the left-hand operand. Also, the value of the left-hand operand is not affected by applying the shift operator.

The shift distance is calculated by AND-ing the value of the right-hand operand with a mask value of 0x1f (31) if the left-hand has the promoted type int, or using a mask value of 0x3f (63) if the left-hand has the promoted type long. This effectively means masking the five lower bits of the right-hand operand in the case of an int left-hand operand, and masking the six lower bits of the right-hand operand in the case of a long left-hand operand. Thus, the shift distance is always in the range 0 to 31 when the promoted type of left-hand operand is int, and in the range 0 to 63 when the promoted type of left-hand operand is long.

Given that a contains the value whose bits are to be shifted and n specifies the number of bits to shift, the bitwise operators are defined in Table 3.18. It is implied that the value n in Table 3.18 is subject to the shift distance calculation outlined above, and that the shift operations are always performed on the value of the left-hand operand represented in 2's complement.

Table 3.18. Shift Operators

Shift left

a << n

Shift all bits in a left n times, filling with 0 from the right.

Shift right with sign bit

a >> n

Shift all bits in a right n times, filling with the sign bit from the left.

Shift right with zero fill

a >>> n

Shift all bits in a right n times, filling with 0 from the left.

Since char, byte and short operands are promoted to int, the result of applying these bitwise operators is always either an int or a long value. Care must be taken in employing a cast to narrow the resulting value, as this can result in loss of information as the upper bits are chopped off during conversion.

Note that regardless of the promotion of the values in the operands or determination of the shift distance, the operands a and n are not affected by these three shift operators. However, the shift compound assignment operators, discussed in this section, can change the value of the left-hand operand a.

Bit values shifted out (falling off) from bit 0 or the most significant bit are lost. Since bits can be shifted both left and right, a positive value when shifted can result in a negative value and vice versa.

The Shift-left Operator <<

As the bits are shifted left, zeros are always filled in from the right.

int i = 12;
int result = i << 4;    // 192

The bits in the int value for i are shifted left four places as follows:

i << 4
= 0000 0000 0000 0000 0000 0000 0000 1100 << 4
= 0000 0000 0000 0000 0000 0000 1100 0000
= 0x000000c0
= 192

Each left-shift corresponds to multiplication of the value by 2. In the above example, 12*24 is 192.

The sign bit of a byte or short value is extended to fill the higher bits when the value is promoted, as illustrated by the example below:

byte  b = -42;           // 11010110
short n = 4;
int   result = b << n;   // -672

The values of the two operands, b and n, in the previous example are promoted individually. The short value in n is promoted to int. The byte value in b, after promotion to int, is shifted left 4 places:

b << n
= 1101 0110 << 0000 0000 0000 0100
= 1111 1111 1111 1111 1111 1111 1101 0110 <<0000 0000 0000 0000 0000 0000 0000 0100
= 1111 1111 1111 1111 1111 1111 1101 0110 << 4
= 1111 1111 1111 1111 1111 1101 0110 0000
= 0xfffffd60
= -672

In the above example, -42*24 is -672.

Care must also be taken when assigning the result of a shift operator to a narrower data type.

byte a = 32, b;
int j;

j = a << 3;            // 256
b = (byte) (a << 3);   // 0. Cast mandatory.

The result of (a << 3) is 256.

a << 3
= 0000 0000 0000 0000 0000 0000 0010 0000 << 3
= 0000 0000 0000 0000 0000 0001 0000 0000
= 0x00000100
= 256

The value j gets is 256, but the value b gets is 0, as the higher bits are discarded in the explicit narrowing conversion.

The examples above do not show how the shift distance is determined. It is obvious from the value of the right-hand operand, which is within the range 0 to 31, inclusive. An example with the shift-left operator, where the value of the right-hand operand is out-of-range, is shown below.

12 << 36
= 0000 0000 0000 0000 0000 0000 0000 1100 << (0...0010 0100 & 0001 1111)
= 0000 0000 0000 0000 0000 0000 0000 1100 << 0...0000 0100
= 0000 0000 0000 0000 0000 0000 0000 1100 << 4
= 0000 0000 0000 0000 0000 0000 1100 0000
= 0x000000c0
= 192

The value of the right-hand operand, 36, is AND-ed with the mask 11111 (i.e., 31, 0x1f ) giving the shift distance 4. This is the same as (36 % 32). It is not surprising that (12 << 36) is equal to (12 << 4) (i.e., 192).

The Shift-right-with-sign-fill Operator >>

As the bits are shifted right, the sign bit (the most significant bit) is used to fill in from the left. So, if the left-hand operand is a positive value, zeros are filled in from the left, but if the operand is a negative value, ones are filled in from the left.

int i = 12;
int result = i >> 2;    // 3

The value for i is shifted right with sign-fill two places.

i >> 2
= 0000 0000 0000 0000 0000 0000 0000 1100 >> 2
= 0000 0000 0000 0000 0000 0000 0000 0011
= 0x00000003
= 3

Each right-shift corresponds to integer division of the value being shifted by two, but this can give unexpected results if care is not exercised, as bits start falling off. In the above example, 12/22 is 3.

Similarly, when a negative value is shifted right, ones are filled in from the left.

byte b = -42;          // 11010110
int result = b >> 4;   // -3

The byte value for b, after promotion to int, is shifted right with sign-fill four places.

b >> 4
= 1111 1111 1111 1111 1111 1111 1101 0110 >> 4
= 1111 1111 1111 1111 1111 1111 1111 1101
= 0xfffffffd
= -3

In the following example, the right-hand operand has a negative value:

-42 >> -4
= 1111 1111 1111 1111 1111 1111 1101 0110 >> (1...1111 1100 & 0001 1111)
= 1111 1111 1111 1111 1111 1111 1101 0110 >> 0...0001 1100
= 1111 1111 1111 1111 1111 1111 1101 0110 >> 28
= 1111 1111 1111 1111 1111 1111 1111 1111
= 0xffffffff
= -1

The value of the right-hand operand, -4, is AND-ed with the mask 11111 (i.e., 31, 0x1f ) giving the shift distance 28. This is the same as (-4 % 32). The value of (-42 >> -4) is equivalent to (-42 >> 28).

The Shift-right-with-zero-fill Operator >>>

As the bits are shifted right, zeros are filled in from the left, regardless of whether the operand has a positive or a negative value.

Obviously, for positive values, the shift-right-with-zero-fill >>> and shift-right-with-sign-fill >> operators are equivalent. The expression (12 >> 2) and the expression (12 >>> 2) return the same value:

12 >>> 2
= 0000 0000 0000 0000 0000 0000 0000 1100 >>> 2
= 0000 0000 0000 0000 0000 0000 0000 0011
= 0x00000003
= 3

Individual unary numeric promotion of the left-hand operand is shown in the following example:

byte b = -42;              // 1101 0110
int result = b >>> 4;      // 268435453

It is instructive to compare the value of the expression (-42 >>> 4) with that of the expression (-42 >> 4), which has the value -3. The byte value for b, after unary numeric promotion to int, is shifted right with zero-fill four places.

b >>> 4
= 1111 1111 1111 1111 1111 1111 1101 0110 >>> 4
= 0000 1111 1111 1111 1111 1111 1111 1101
= 0x0ffffffd
= 268435453

In the following example, the value of the right-hand operand is out-of-range, resulting in a shift distance of 28 (as we have seen before):

-42 >>> -4
= 1111 1111 1111 1111 1111 1111 1101 0110 >>> 28
= 0000 0000 0000 0000 0000 0000 0000 1111
= 0x0000000f
= 15

Shift Compound Assignment Operators: <<=, >>=, >>>=

Table 3.19 lists shift compound assignment operators. Type conversions for these operators, when applied to integral operands, are the same as for other compound assignment operators: An implicit narrowing conversion is performed on assignment when the destination data type is either byte, short, or char.

Table 3.19. Shift Compound Assignment Operators

Expression

Given T as the Integral Type of x, the Expression Is Evaluated as:

x <<= a

x = (T) ((x) << (a))

x >>= a

x = (T) ((x) >> (a))

x >>>= a

x = (T) ((x) >>> (a))

Examples of Shift Compound Assignment Operators
int i = -42;
i >>= 4;                    // 1...1101 0110 >> 4 => 1...1111 1101 (= -3).

byte a = 12;
a <<= 5;                    // (1) -128. Evaluated as a = (byte)((int)a << 5)
a = a << 5;                 // Compile-time error. Needs explicit cast.

The example at (1) illustrates the truncation that takes place on narrowing to destination type. The byte value in a is first promoted to int (by applying unary numeric promotion in this case), shifted left five places, followed by implicit narrowing to byte:

a = (byte) (a << 5)
  = (byte) (0000 0000 0000 0000 0000 0000 0000 1100 << 5)
  = (byte)  0000 0000 0000 0000 0000 0001 1000 0000
  = 1000 0000
  = 0x80
  = -128


     
    ASPTreeView.com
     
    Evaluation has ї·µЙexpired.
    Info...