Shifting
Two additional operators are left shift and right shift:
- << left shift
- >> right shift
>> shifts bits by n positions to the right. For example, if you take the string:
0011 1111 //decimal value: 63
Shifting it by one position to the right produces:
0001 1111 //decimal value: 31
BYTE s1 = 63; //0x3f, 0011 1111
BYTE result =
s1 >> 1; // 0x1f, 0001 1111
A graphic illustration of this operation may demystify the underlying steps. First, you have an eight bit string whose boundaries are marked with a pair of bars:
|0011 1111|
The right shift operation causes the leftmost bit's position to become empty (indicated by an underscore). The rightmost bit overflows outside the string's boundaries:
|_0011 111|1
In the second step, the processor pads empty positions with zeros and discards bits that were pushed outside the string's boundaries (this rule applies only to unsigned types; the effect of shifting signed values is machine-dependent):
|00011 111|_
Of course, these steps don't necessarily correspond to the underlying machine instructions that your processor employs but the effect is the same.
Bit shifting happens to be a very efficient operation. This is why time-critical applications often use shift operators as a faster alternative to the division and multiplication operators. In the above example, the shift operation has the same effect as dividing the original value by two. In a similar vein, you can get the effect of multiplying a number by two if you apply the left shift operator. For example, left shifting the number 63 by one position produces 126:
BYTE s1 = 63; // 0x3f, 0011 1111
BYTE res = s1 << 1; //dec 126, 0x73, 0111 1110
Using the self-assignment versions of these operators, the previous code can be rewritten like this:
BYTE s1 = 63; //0x3f, 0011 1111
// the expression 's1 >> 2;' divides s1 by 4
s1 >>= 2; // 15, 0x0f, 0000 1111
Wise Up
Bitwise operators are useful in
bit masking, i.e., setting or examining bits in a bit string. Take for example a simple word processing application. The text in a document (or a portion thereof) may have the following features: bold, italics, underlined, or none. Each of these features can be represented as an individual bit:
const BYTE BOLD = 0x01; // first bit
const BYTE ITAL = 0x02; // second bit
const BYTE UNDERL = 0x04; // third bit
Users may combine some of these features, all of them or none:
BYTE style = BOLD | ITAL;//turn on bold and italics
The following code tests whether underline and bold are on using bit masks:
bool isul=style & UNDERL; // false
bool isbold=style & BOLD; // true