1.1.
Bitwise operators
The bitwise operators treat their operands
as a series of individual bits rather than a numerical value. They work only
with integer variables or integer constants as operands, so only data types short , int , long , long long , signed char
, and char , as well as the unsigned variants of these,can be used. The bitwise
operators are useful in programming hardware devices, where the status of a
device is often represented as a series of individual fl ags (that is, each bit
of a byte may signify the status of a different aspect of the device), or for
any situation where you might want to pack a set of on  off fl ags into a
single variable. You will see them in action when you look at input/output in detail,
where single bits are used to control various options in the way data is
handled.
There are six bitwise operators:
& bitwise AND

 bitwise OR

^ bitwise exclusive OR

~ bitwise NOT

> > shift right

> > shift right

The following sections take a look at how
each of them works.
1.1.1.
The Bitwise AND
The bitwise AND, & , is a binary
operator that combines corresponding bits in its operands in a particular way.
If both corresponding bits are 1, the result is a 1 bit, and if either or both
bits are 0, the result is a 0 bit. The effect of a particular binary operator
is often shown using what is called a truth table . This shows, for various
possible combinations of operands, what the result is. The truth table for
& is as follows:
Bitwise AND

0

1

0

0

0

1

0

1

For each row and column combination, the
result of & combining the two is the entry at the intersection of the row
and column. You can see how this works in an example:
char letter1 = 'A', letter2 = 'Z', result =
0;
result = letter1 & letter2;
You need to look at the bit patterns to see
what happens. The letters ‘ A ’ and ‘ Z ’ correspond to hexadecimal values 0x41
and 0x5A, respectively. You can confirm this by looking at how corresponding bits
combine with & in the truth table. After the assignment, result will have
the value 0x40, which corresponds to the character " @ ". Because the
& produces zero if either bit is zero, you can use this operator to make
sure that unwanted bits are set to 0 in a variable. You achieve this by creating
what is called a “mask” and combining with the original variable using & .
You create the mask by specifying a value that has 1 where you want to keep a
bit, and 0 where you want to set a bit to zero. The result of AND  ing the mask
with another integer will be 0 bits where the mask bit is 0, and the same value
as the original bit in the variable where the mask bit is 1. Suppose you have a
variable letter of type char where, for the purposes of illustration, you want
to eliminate the high  order 4 bits, but keep the low – order 4 bits. This is
easily done by setting up a mask as 0x0F and combining it with the value of
letter using & like this:
letter = letter & 0x0F;
or, more concisely:
letter & = 0x0F;
If letter started out as 0x41 , it would
end up as 0x01 as a result of either of these statements. The 0 bits in the mask cause corresponding
bits in letter to be set to 0, and the 1 bits in the mask cause corresponding
bits in letter to be kept as they are. Similarly, you can use a mask of 0xF0 to
keep the 4 high  order bits, and zero the 4 low  order bits. Therefore, this
statement,
letter & = 0xF0;
will result in the value of letter being
changed from 0x41 to 0x40 .
1.1.2.
The Bitwise OR
The bitwise OR,  , sometimes called the
inclusive OR , combines corresponding bits such that the result is a 1 if
either operand bit is a 1, and 0 if both operand bits are 0. The truth table
for the bitwise OR is:
Bitwise OR

0

1

0

0

1

1

1

0

You can exercise this with an example of
how you could set individual flags packed into a variable of type int. Suppose
that you have a variable called style of type short that contains 16 individual
1  bitflags. Suppose further that you are interested in setting individual flags
in the variable style. One way of doing this is by defining values that you can
combine with the OR operator to set particular bits on. To use in setting the
rightmost bit, you can define:
short vredraw = 0x01;
For use in setting the second  to 
rightmost bit, you could define the variable hredraw as:
short hredraw = 0x02;
So, you could set the rightmost two bits in
the variable style to 1 with the statement:
style = hredraw  vredraw;
Of course, to set the third bit of style to
1, you would use the constant 0x04. Because the OR operation results in 1 if
either of two bits is a 1, OR  ing the two variables together produces a
result with both bits set on. may have been set elsewhere. You can do this
quite easily with a statement such as:
style = hredraw  vredraw;
This statement will set the two rightmost
bits of the variable style to 1, leaving the others at whatever they were
before the execution of this statement.
1.1.3.
The Bitwise Exclusive OR
The exclusive OR, ^ , is so called because
it operates similarly to the inclusive OR but produces 0 when both operand bits
are 1. Therefore, its truth table is as follows:
Bitwise EOR

0

1

0

0

1

1

1

0

Using the same variable values that we used
with the AND, you can look at the result of the following statement:
result = letter1 ^ letter2;
This operation can be represented as:
letter1 0100 0001
letter2 0101 1010
EOR  ed together produce:
result 0001 1011
The variable result is set to 0x1B , or 27
in decimal notation. The ^ operator has a rather surprising property. Suppose
that you have two char variables, first with the value ‘ A ’ , and last with
the value ‘ Z ’ , corresponding to binary values 0100 0001 and 0101 1010. If
you write the statements,
first ^= last; // Result first is 0001 1011
last ^= first; // Result last is 0100 0001
first ^= last; // Result first is 0101 1010
the result of these is that first and last
have exchanged values without using any intermediate memory location. This
works with any integer values.
1.1.4.
The Bitwise NOT
The bitwise NOT, ~ , takes a single
operand, for which it inverts the bits: 1 becomes 0, and 0 becomes 1. Thus, if
you execute the statement,
result = ~letter1;
if letter1 is 0100 0001, the variable
result will have the value 1011 1110, which is 0xBE, or 190 as a decimal value.
1.1.5.
The Bitwise Shift Operators
These operators shift the value of an integer
variable a specified number of bits to the left or right. The operator >
> is for shifts to the right, while < < is the operator for shifts to
the left. Bits that “fall off ” either end of the variable are lost.
You declare and initialize a variable
called number with the statement:
unsigned short number = 16387U;
As you saw earlier in this chapter, you
write unsigned integer literals with a letter U or u appended to the number.
You can shift the contents of this variable to the left with the statement:
number < < = 2; // Shift left two bit
positions
The left operand of the shift operator is
the value to be shifted, and the number of bit positions that the value is to
be shifted is specified by the right operand. The illustration shows the effect
of the operation. As you can see, shifting the value 16,387 two positions to
the left produces the value 12.The rather drastic change in the value is the
result of losing the high  order bit when it is shifted out. You can also shift
the value to the right. Let’s reset the value of number to its initial value of
16,387. Then you can write:
number > > = 2; // Shift right two
bit positions
This shifts the value 16,387 two positions
to the right, storing the value 4,096. Shifting right 2 bits is effectively
dividing the value by 4 (without remainder). This is also shown in the
illustration. As long as bits are not lost, shifting n bits to the left is
equivalent to multiplying the value by 2, n times. In other words, it is equivalent
to multiplying by 2 n. Similarly, shifting right n bits is equivalent to
dividing by 2 n. But beware: as you saw with the left shift of the variable
number, if significant bits are lost, the result is nothing like what you would
expect. However, this is no different from the multiply operation. If you
multiplied the 2  byte number by 4, you would get the same result, so shifting
left and multiply are still equivalent. The problem of accuracy arises because the
value of the result of the multiplication is outside the range of a 2  byte
integer. You might imagine that confusion could arise between the operators
that you have been using for input and output and the shift operators. As far
as the compiler is concerned, the meaning will always be clear from the
context. If it isn ’ t, the compiler will generate a message, but you need to
be careful. For example, if you want to output the result of shifting a variable
number left by 2 bits, you could write the following statement:
cout < < (number < < 2);
Here, the parentheses are essential.
Without them, the shift operator will be interpreted by the compiler as a
stream operator, so you won’t get the result that you intended; the output will
be the value of number followed by the value 2. The right  shift operation is
similar to the left  shift. For example, suppose the variable number has the
value 24, and you execute the following statement:
number > > = 2;
This will result in number having the value
6, effectively dividing the original value by 4. However, the right shift
operates in a special way with signed integer types that are negative (that is,
the sign bit, which is the leftmost bit, is 1). In this case, the sign bit is
propagated to the right. For example, declare and initialize a variable number
of type char with the value 104 in
decimal:
char number = 104; // Binary
representation is 1001 1000
Now you can shift it right 2 bits with the
operation:
number > > = 2; // Result 1110 0110
The decimal value of the result is 26, as the sign bit is repeated. With
operations on unsigned integer types, of course, the sign bit is not repeated
and zeros appear.
You may be wondering how the shift operators,
< < and > > , can be the same as the operators used with the
standard streams for input and output. These operators can have different
meanings in the two contexts because cin and cout are stream objects, and
because they are objects, it is possible to redefine the meaning of operators
in context by a process called operator overloading. Thus, the > >
operator has been redefined for input stream objects such as cin , so you can
use it in the way you have seen. The < < operator has also been redefi
ned for use with output stream objects such as cout.