Submitted by tushar pramanick on Tue, 03/05/2013 - 21:08

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)

Related Items

মডুলার C প্রোগ্রামিং (Modular C Programming)

কেবল মাত্র একটি ফাংশন দিয়ে কোনো বড়ো জটিল সমস্যা সমাধানের চেষ্টা করা ভাল প্রোগ্রামিংয়ের পদ্ধতি নয়। সঠিক পদ্ধতি হ'ল সমস্যাটিকে কয়েকটি ছোট ছোট এবং সরল টুকরো করে ফেলা যাতে তা আরও বিশদে বোঝা যায় । তারপরে এই ছোট এবং সরল সমস্যাগুলি সমাধান করার জন্য ছোট ছোট ফাংশন ব্লক তৈরি করা এবং পরে সেগুলি নিয়মানুযায়ী সংযোজিত করা ।

Programming Style

Programming Style

In this section, I'd like to briefly highlight some points that will help you write clean programs that can easily be read, understood, and maintained.

Exercises : Answer the following Question

To help solidify your understanding of this hour's lesson, you are encouraged to answer the quiz questions and finish the exercises provided in the Workshop before you move to the next lesson.

Question and Answer

    Q Is the C preprocessor part of the C compiler?

    A No. The C preprocessor is not part of the C compiler. With its own line-oriented grammar and syntax, the C preprocessor runs before the compiler in order to handle named constants, macros, and inclusion of files.

Compiling Your Code Under Conditions

Compiling Your Code Under Conditions

You can select portions of your C program that you want to compile by using a set of preprocessor directives. This is useful, especially when you're testing a piece of new code or debugging a portion of code.