Manipulating Bits
In previous hours, you learned that computer data and files are made of bits (or bytes). There is even an operator in C_the sizeof operator_that can be used to measure the number of bytes for data types.
In this section, you'll learn about a set of operators that enable you to access and manipulate specific bits.
There are six bit-manipulation operators in the C language:
Operator Description
& The bitwise AND operator
| The bitwise OR operator
^ The bitwise exclusive OR (XOR) operator
~ The bitwise complement operator
>> The right-shift operator
<< The left-shift operator
The following two sections give explanations and examples of the bit-manipulation
operators.
TIP
It's easy to convert a decimal number into a hex or a binary. Each digit in a hex number consists of four bits. A bit represents a digit in a binary number. Table 8.4 shows the hex numbers (0_F) and their corresponding binary and decimal representations.
Table 8.4. Numbers expressed in different formats.
Hex Binary Decimal
0 0000 0
1 0001 1
2 0010 2
3 0011 3
4 0100 4
5 0101 5
6 0110 6
7 0111 7
8 1000 8
9 1001 9
A 1010 10
B 1011 11
C 1100 12
D 1101 13
E 1110 14
F 1111 15
Let's see how to convert a decimal number into a binary, or vice versa. As we know, that binary is a 2-based numbering system. Each digit in a binary number is called a bit and can be 1 or 0. If the position of a bit in a binary number is n, then the bit can have a value of 2 to the power of n. The position of a bit in a binary number is counted from the right of the binary number. The most-right bit is at the position of zero. Thus, given a binary number 1000, we can calculate its decimal value like this:
1000 -> 1 * 23 + 0 *22 + 0 * 21 + 0 * 20-> 23 -> 8 (decimal)
That is, the decimal vale of the binary number 1000 is 8.
If we want to convert a decimal number, for example 10, to its binary counterpart, we have the following process:
10 -> 23 + 21 -> 1 *23 + 0 * 22 + 1 *21 + 0 * 20 -> 1010 (binary)
Likewise, you can convert the rest of the decimal numbers in Table 8.4 to their binary counterparts, or vice versa.
Using Bitwise Operators
The general forms of the bitwise operators are as follows:
x & y
x | y
x ^ y
~x
Here x and y are operands.
The & operator compares each bit of x to the corresponding bit in y. If both bits are 1, 1 is placed at the same position of the bit in the result. If one of the bits, or two of them, is 0, 0 is placed in the result.
For instance, the expression with two binary operands, 01 & 11, returns 01.
The | operator, however, places 1 in the result if either operand is 1. For example, the expression 01 | 11 returns 11.
The ^ operator places 1 in the result if either operand, but not both, is 1. Therefore, the expression 01 ^ 11 returns 10.
Finally, the ~ operator takes just one operand. This operator reverses each bit in the operand. For instance, ~01 returns 10.
Table 8.5 shows more examples of using the bitwise operators in decimal, hex, and binary formats (in the left three columns). The corresponding results, in binary, hex, and decimal formats, are listed in the right three columns. The hex numbers are prefixed with 0x.
Table 8.5. Examples of using bitwise operators.
Decimal Results
Expressions Hex Binary Decimal Hex Binary
12 & 10 0x0C & 0x0A 1100 &1010 8 0x08 1000
12 | 10 0x0C | 0x0A 1100 | 1010 14 0x0E 1110
12 ^ 10 0x0C ^ 0x0A 1100 ^ 1010 6 0x06 0110
~12 ~0x000C ~0000000000001100 65523 FFF3 1111111111110011
TYPE
Note that the complementary value of 12 is 65523, because the unsigned integer data type (16-bit) has the maximum number 65535. In other words, 65,523 is the result of subtracting 12 from 65,535. (The unsigned data modifier is introduced in Hour 9, "Playing with Data Modifiers and Math Functions.")
The program in Listing 8.5 demonstrates the usage of the bitwise operators.
Listing 8.5. Using bitwise operators.
1: /* 08L05.c: Using bitwise operators */
2: #include <stdio.h>
3:
4: main()
5: {
6: int x, y, z;
7:
8: x = 4321;
9: y = 5678;
10: printf("Given x = %u, i.e., 0X%04X\n", x, x);
11: printf(" y = %u, i.e., 0X%04X\n", y, y);
12: z = x & y;
13: printf("x & y returns: %6u, i.e., 0X%04X\n", z, z);
14: z = x | y;
15: printf("x | y returns: %6u, i.e., 0X%04X\n", z, z);
16: z = x ^ y;
17: printf("x ^ y returns: %6u, i.e., 0X%04X\n", z, z);
18: printf(" ~x returns: %6u, i.e., 0X%04X\n", ~x, ~x);
19: return 0;
20: }
OUTPUT
After the executable, 08L05.exe, is created and run from a DOS prompt, the following output is shown on the screen:
C:\app> 08L05
Given x = 4321, i.e., 0X10E1
y = 5678, i.e., 0X162E
x & y returns: 4128, i.e., 0X1020
x | y returns: 5871, i.e., 0X16EF
x ^ y returns: 1743, i.e., 0X06CF
~x returns: 61214, i.e., 0XEF1E
C:\app>
ANALYSIS
In Listing 8.5, three integer variables, x, y, and z, are declared in line 6. Lines 8 and 9 set x and y to 4321 and 5678, respectively. Lines 10 and 11 then print out the values of x and y in both decimal and hex formats. The hex numbers are prefixed with 0X.
The statement in line 12 assigns the result of the operation made by the bitwise AND operator (&) with the variables x and y. Then, line 13 displays the result in both decimal and hex formats.
Lines 14 and 15 perform the operation specified by the bitwise operator (|) and print out the result in both decimal and hex formats. Similarly, lines 16 and 17 give the result of the operation made by the bitwise XOR operator (^).
Last, the statement in line 18 prints out the complementary value of x by using the bitwise complement operator (~). The result is displayed on the screen in both decimal and hex formats.
Note that the unsigned integer format specifier with a minimum field width of 6, %6u, and the uppercase hex format specifier with the minimum width of 4, %04X, are used in the printf() function. The unsigned integer data type (that is, the non-negative integer data type) is chosen so that the complementary value of an integer can be shown and understood easily. More details on the unsigned data modifier are introduced in Hour 9.
WARNING
Don't confuse the bitwise operators & and | with the logical operators && and ||. For instance,
(x=1) & (y=10)
(x=1) && (y=10)
- 233 views