When using the bitwise operators, it’s useful to illustrate their precise effects by printing values in their binary representation. The program of Fig. 20.6 prints an unsigned
integer in its binary representation in groups of eight bits each.
1 // Fig. 20.6: fig20_06.cpp
2 // Printing an unsigned integer in bits.
3 #include <iostream>
4 #include <iomanip>
5 using namespace std;
6
7 void displayBits( unsigned ); // prototype
8
9 int main()
10 {
11 unsigned inputValue = 0; // integral value to print in binary
12
13 cout << "Enter an unsigned integer: ";
14 cin >> inputValue;
15 displayBits( inputValue );
16 } // end main
17
18 // display bits of an unsigned integer value
19 void displayBits( unsigned value )
20 {
21 const int SHIFT = 8 * sizeof( unsigned ) - 1;
22 const unsigned MASK = 1 << SHIFT;
23
24 cout << setw( 10 ) << value << " = ";
25
26 // display bits
27 for ( unsigned i = 1; i <= SHIFT + 1; ++i )
28 {
29 cout << ( value & MASK ? '1' : '0' );
30 value <<= 1; // shift value left by 1
31
32 if ( i % 8 == 0 ) // output a space after 8 bits
33 cout << ' ';
34 } // end for
35
36 cout << endl;
37 } // end function displayBits
Enter an unsigned integer: 65000
65000 = 00000000 00000000 11111101 11101000
Enter an unsigned integer: 29
29 = 00000000 00000000 00000000 00011101
Function displayBits
(lines 19–37) uses the bitwise AND operator to combine variable value
with constant MASK
. Often, the bitwise AND operator is used with an operand called a mask—an integer value with specific bits set to 1
. Masks are used to hide some bits in a value while selecting other bits. In displayBits
, line 22 assigns constant MASK
the value 1 << SHIFT
. The value of constant SHIFT
was calculated in line 21 with the expression
8 * sizeof( unsigned ) - 1
which multiplies the number of bytes an unsigned
object requires in memory by 8
(the number of bits in a byte) to get the total number of bits required to store an unsigned
object, then subtracts 1. The bit representation of 1 << SHIFT
on a computer that represents unsigned
objects in four bytes of memory is
10000000 00000000 00000000 00000000
The left-shift operator shifts the value 1
from the low-order (rightmost) bit to the high-order (leftmost) bit in MASK
, and fills in 0
bits from the right. Line 29 prints a 1
or a 0
for the current leftmost bit of variable value
. Assume that variable value
contains 65000
(00000000 00000000 11111101 11101000
). When value
and MASK
are combined using &
, all the bits except the high-order bit in variable value
are “masked off” (hidden), because any bit “ANDed” with 0
yields 0
. If the leftmost bit is 1
, value & MASK
evaluates to
00000000 00000000 11111101 11101000 (value)
10000000 00000000 00000000 00000000 (MASK)
-----------------------------------
00000000 00000000 00000000 00000000 (value & MASK)
which is interpreted as false
, and 0
is printed. Then line 30 shifts variable value
left by one bit with the expression value <<= 1
(i.e., value = value << 1
). These steps are repeated for each bit variable value
. Eventually, a bit with a value of 1
is shifted into the leftmost bit position, and the bit manipulation is as follows:
11111101 11101000 00000000 00000000 (value)
10000000 00000000 00000000 00000000 (MASK)
-----------------------------------
10000000 00000000 00000000 00000000 (value & MASK)
Because both left bits are 1
s, the expression’s result is nonzero (true) and 1
is printed. Figure 20.7 summarizes the results of combining two bits with the bitwise AND operator.
Common Programming Error 20.2
Using the logical AND operator (&&) for the bitwise AND operator (&) and vice versa is a logic error.
The program of Fig. 20.8 demonstrates the bitwise AND operator, the bitwise inclusive OR operator, the bitwise exclusive OR operator and the bitwise complement operator. Function displayBits
(lines 48–66) prints the unsigned
integer values.
1 // Fig. 20.8: fig20_08.cpp
2 // Bitwise AND, inclusive OR,
3 // exclusive OR and complement operators.
4 #include <iostream>
5 #include <iomanip>
6 using namespace std;
7
8 void displayBits( unsigned ); // prototype
9
10 int main()
11 {
12 // demonstrate bitwise &
13 unsigned number1 = 2179876355;
14 unsigned mask = 1;
15 cout << "The result of combining the following
";
16 displayBits( number1 );
17 displayBits( mask );
18 cout << "using the bitwise AND operator & is
";
19 displayBits( number1 & mask );
20
21 // demonstrate bitwise |
22 number1 = 15;
23 unsigned setBits = 241;
24 cout << "
The result of combining the following
";
25 displayBits( number1 );
26 displayBits( setBits );
27 cout << "using the bitwise inclusive OR operator | is
";
28 displayBits( number1 | setBits );
29
30 // demonstrate bitwise exclusive OR
31 number1 = 139;
32 unsigned number2 = 199;
33 cout << "
The result of combining the following
";
34 displayBits( number1 );
35 displayBits( number2 );
36 cout << "using the bitwise exclusive OR operator ^ is
";
37 displayBits( number1 ^ number2 );
38
39 // demonstrate bitwise complement
40 number1 = 21845;
41 cout << "
The one's complement of
";
42 displayBits( number1 );
43 cout << "is" << endl;
44 displayBits( ~number1 );
45 } // end main
46
47 // display bits of an unsigned integer value
48 void displayBits( unsigned value )
49 {
50 const int SHIFT = 8 * sizeof( unsigned ) - 1;
51 const unsigned MASK = 1 << SHIFT;
52
53 cout << setw( 10 ) << value << " = ";
54
55 // display bits
56 for ( unsigned i = 1; i <= SHIFT + 1; ++i )
57 {
58 cout << ( value & MASK ? '1' : '0' );
59 value <<= 1; // shift value left by 1
60
61 if ( i % 8 == 0 ) // output a space after 8 bits
62 cout << ' ';
63 } // end for
64
65 cout << endl;
66 } // end function displayBits
The result of combining the following
2179876355 = 10000001 11101110 01000110 00000011
1 = 00000000 00000000 00000000 00000001
using the bitwise AND operator & is
1 = 00000000 00000000 00000000 00000001
The result of combining the following
15 = 00000000 00000000 00000000 00001111
241 = 00000000 00000000 00000000 11110001
using the bitwise inclusive OR operator | is
255 = 00000000 00000000 00000000 11111111
The result of combining the following
139 = 00000000 00000000 00000000 10001011
199 = 00000000 00000000 00000000 11000111
using the bitwise exclusive OR operator ^ is
76 = 00000000 00000000 00000000 01001100
The one's complement of
21845 = 00000000 00000000 01010101 01010101
is
4294945450 = 11111111 11111111 10101010 10101010
3.14.73.229