More on Handling Basic Data Types - Using the Bitwise AND
(Page 5 of 13 )
You’ll typically use the bitwise AND operator to select particular bits or groups of bits in an integer value. To see what this means, you can reuse the example presented at the beginning of this section, which used a 16-bit integer to store the characteristics of a font.
Suppose you want to declare and initialize a variable to specify a 12-point, italic, style 6 font—in fact, the very same one illustrated in Figure 3-1. In binary, the style will be 00000110, the italic bit will be 1, the bold bit will be 0, and the size will be 01100. Remembering that there’s an unused bit as well, you need to initialize the value of the font variable to the binary number 0000 0110 0100 1100.
Because groups of four bits correspond to a hexadecimal digit, the easiest way to do this is to specify the initial value in hexadecimal notation:
unsigned short font = 0x064C; // Style 6, italic, 12
point
NOTE When you set up bit patterns like this, hexadecimal notation is invariably more appropriate than using decimal values.
To use the size, you need to be able to extract it from the font variable; the bitwise AND operator will enable you to do this. Because bitwise AND only produces 1 bit when both bits are 1, you can define a value that will “select” the bits defining the size when you AND it with font. All you need to do is define a value that contains 1s in the bit positions that you’re interested in, and 0s in all the others. This kind of value is called a mask, and you can define such a mask with the statement
unsigned short size_mask = 0x1F; // Mask is 0000 0000
0001 1111 to select size
The five low-order bits of font represent its size, so you set these bits to 1. The remaining bits are 0, so they will be discarded. (Binary 0000 0000 0001 1111 translates to hexadecimal 1F.)
You can now extract the point size from font with the statement
unsigned short size = font & size_mask;
Where both corresponding bits are 1 in an & operation, the resultant bit is 1. Any other combination of bits results in 0. The values therefore combine like this:
font 0000 0110 0100 1100
size_mask 0000 0000 0001 1111
font & size_mask 0000 0000 0000 1100
Showing the binary values in groups of four bits has no real significance other than making it easy to identify the hexadecimal equivalent; it also makes it easier to see how many bits there are in total. As you can see, the effect of the mask is to separate out the five rightmost bits, which represent the point size.
You could use the same mechanism to select out the style for the font, but you’ll also need to use a shift operator to move the style value to the right. You can define a mask to select the left eight bits as follows:
unsigned short style_mask = 0XFF00; // Mask is 1111
1111 0000 0000 for style
You can then obtain the style value with the statement
unsigned short style = (font & style_mask) >> 8; //
Extract the style
The effect of this statement is
font 0000 0110 0100 1100
style_mask 1111 1111 0000 0000
font & style_mask 0000 0110 0000 0000
(font & style_mask) >> 8 0000 0000 0000 0110
You should be able to see that you could just as easily isolate the bits indicating italic and bold by defining a mask for each, with the appropriate bit set to 1. Of course, you still need a way to test whether the resulting bit is 1 or 0, and you’ll see how to do that in the next chapter.
Another use for the bitwise AND operator is to turn bits off. Part of the effect you saw previously is that any bit that is 0 in a mask will produce 0 in the result. To turn the italic bit off, for example, and leave the rest unchanged, you just bitwise-AND the font variable with a mask that has the italic bit as 0 and all the other bits as 1. You’ll look at the code to do this in the context of the bitwise OR operator, for reasons that I’ll explain next.
Using the Bitwise OR
You can use the bitwise OR operator for setting single or multiple bits. Continuing with your manipulations of the font variable, it’s conceivable that you would want to set the italic and bold bits on demand. You can define masks to select these bits with the statements
unsigned short italic = 0X40U; // Seventh bit from
the right
unsigned short bold = 0X20U; // Sixth bit from the
right
Now you can set the bold bit with the statement
font |= bold; // Set bold
The bits combine here as follows:
font 0000 0110 0100 1100
bold 0000 0000 0010 0000
font | bold 0000 0110 0110 1100
Now, the
font variable specifies that the font it represents is bold as well as italic. Note that this operation will result in the bit being set, regardless of its previous state. If it was on before, it remains on.
You can also set multiple bits by ORing the masks together, so the following statement will set both the bold and the italic bit:
font |= bold | italic; // Set bold and italic
It’s easy to fall into the trap of allowing language to make you select the wrong operator. Because you say “Set italic and bold” there’s a temptation to use the & operator, but this would be wrong. ANDing the two masks together would result in a value with all bits 0, so you wouldn’t change anything.
As I said at the end of the last section, you can use the & operator to turn bits off— you just need a mask that contains a 0 at the position of the bit you want to turn off and 1 everywhere else. However, this raises the issue of how you specify such a mask. If you want to specify it explicitly, you’ll need to know how many bytes there are in your variable—not exactly convenient if you want your program to be in any way portable. However, you can obtain the mask that you want by using the bitwise complement operator on the mask that you would normally use to turn the bit on. You can obtain the mask to turn bold off from the bold mask itself:
bold 0000 0000 0010 0000
~bold 1111 1111 1101 1111
The effect of the complement operator is that each bit in the original is flipped, 0 to 1 or 1 to 0. You should be able to see that this will produce the result you’re looking for, regardless of whether the bold variable occupies 2, 4, or 8 bytes.
NOTE The bitwise complement operator is sometimes called the NOT operator, because for every bit it operates on, what you get is not what you started with.
Thus, all you need to do when you want to turn bold off is to bitwise-AND the complement of the mask, bold, with the variable, font. The following statement will do it:
font &= ~bold; // Turn bold off
You can also set multiple bits to 0 by combining several masks using the & operator, and then bitwise-ANDing the result with the variable you want to modify:
font &= ~bold & ~italic; // Turn bold and italic off
This sets both the italic and bold bits to 0 in the font variable. Note that no parentheses are necessary here, because ~ has a higher precedence than &. However, if you’re ever uncertain about operator precedence, put parentheses in to express what you want. It certainly does no harm, and it really does good when they’re necessary.
This article is excerpted from Beginning ANSI C++ The Complete Language by Ivor Horton (Apress, 2004; ISBN 1590592271). Check it out at your favorite bookstore today. Buy this book now. |
Next: Using the Bitwise Exclusive OR >>
More C++ Articles
More By Apress Publishing