THE Java™ Programming Language, Fourth Edition

(Jeff_L) #1

either bit is 1, and the XOR of two bits yields a 1 only if the two bits have different values. For example:


0xf00f & 0x0ff0 yields 0x0000
0xf00f | 0x0ff0 yields 0xffff
0xaaaa ^ 0xffff yields 0x5555


There is also a unary bitwise complement operator ~, which toggles each bit in its operand. An int with
value 0x00003333 has a complemented value of 0xffffcccc.


Although the same characters are used for the bitwise operators and the logical operators, they are quite
distinct. The types of the operands determine whether, for example, & is a logical or a bitwise AND. Since
logical operators only apply to booleans and bitwise operators only apply to integer types, any expression
involving operands of the different types, such as TRue&0xaaaa, is a compile-time error.


There are other bit manipulation operators to shift bits within an integer value:


<< Shift bits left, filling with zero bits on the right-hand side

>> Shift bits right, filling with the highest (sign) bit on the left-hand side

>>> Shift bits right, filling with zero bits on the left-hand side

The left-hand side of a shift expression is what is shifted, and the right-hand side is how much to shift. For
example, var>>> 2 will shift the bits in var two places to the right, dropping the bottom two bits from the
end and filling the top two bits with zero.


The two right-shift operators provide for an arithmetic shift (>>) and a logical shift (>>>). The arithmetic
shift preserves the sign of the value by filling in the highest bit positions with the original sign bit (the bit in
the highest position). The logical shift inserts zeroes into the high-order bits. It is often used when extracting
subsets of bits from a value. For example, in binary coded decimal (BCD) each decimal digit is represented by
four bits (0x00 to 0x09the remaining bit patterns are invalid) and so every byte can encode two decimal
digits. To extract the low-order digit you AND the byte with a mask of 0x0f to zero out the high-order digit.
To extract the high-order digit you logically right-shift the value by four positions, moving the valid bits down
to the least significant positions and filling the new high-order bits with zero:


class BCD {
static int getBCDLowDigit(byte val) {
return (val & 0x0f);
}
static int getBCDHighDigit(byte val) {
return val >>> 4 ;
}
}


Shift operators have a slightly different type rule from most other binary integer operations. For shift
operators, the resulting type is the type of the left-hand operandthat is, the value that is shifted. If the left-hand
side of the shift is an int, the result of the shift is an int, even if the shift count is provided as a long.


If the shift count is larger than the number of bits in the word, or if it is negative, the actual count will be
different from the provided count. The actual count used in a shift is the count you provide, masked by the
size of the type minus one. For a 32-bit int, for example, the mask used is 0x1f ( 31 ), so both (n<<35)
and (n<<-29) are equivalent to (n<<3).

Free download pdf