Home arrow C++ arrow Page 7 - More on Handling Basic Data Types
C++

More on Handling Basic Data Types


Have you ever wanted to learn how basic types of C++ variables interact in complex situations? Ivor Horton explains this, and also describes some interesting features of C++. This article is from chapter 3 of Ivor Horton's Beginning ANSC C++ The Complete Language (Apress, 2004; ISBN 1590592271).

Author Info:
By: Apress Publishing
Rating: 4 stars4 stars4 stars4 stars4 stars / 10
March 02, 2005
TABLE OF CONTENTS:
  1. · More on Handling Basic Data Types
  2. · Try It Out: Explicit Casting
  3. · Finding Out About Types
  4. · Try It Out: Finding the Sizes of Data Types
  5. · Using the Bitwise AND
  6. · Using the Bitwise Exclusive OR
  7. · Try It Out: Using the Bitwise Operators
  8. · More on Output Manipulators
  9. · Enumerated Data Types
  10. · Try It Out: Enumerated Data Types
  11. · The Lifetime of a Variable
  12. · Try It Out: The Scope Resolution Operator
  13. · Declaring External Variables

print this article
SEARCH DEVARTICLES

More on Handling Basic Data Types - Try It Out: Using the Bitwise Operators
(Page 7 of 13 )

You can put together an example that exercises the bitwise operators, so that you can see them working together. You can also illustrate the use of the exclusive OR for switching between two values, and how you use masks to select and set individual bits. Here’s the code:

// Program 3.4 Using the bitwise operators
#include <iostream>
#include <iomanip>
using std::cout;
using std::endl;
using std::setfill;
using std::setw;
int main() {
 
unsigned long red = 0XFF0000UL;   // Color red
 
unsigned long white = 0XFFFFFFUL; // Color white -  RGB 
       all maximum
 
cout << std::hex;                 // Set hexadecimal
       output format
 cout << setfill('0');             // Set fill character
       for output
 cout << "\nTry out bitwise AND and OR operators.";
 
cout << "\nInitial value red      = " << setw(8) << red;
 cout << "\nComplement ~red        = " << setw(8) << ~red;
 cout << "\nInitial value white    = " << setw(8) << white;
 
cout << "\nComplement   ~white      = " << setw(8) <<
       ~white;
 
cout << "\n Bitwise AND red & white = " << setw(8) << 
       (red  & white);
 
cout << "\n Bitwise OR red | white  = " << setw(8) << 
       (red | white);
 
cout << "\n\nNow we can try out successive exclusive OR 
        operations.";
 
unsigned long mask = red ^ white;
 cout << "\n      mask = red ^ white = " << setw(8) << 
        mask;
 
cout << "\n             mask ^ red = " << setw(8) << 
       (mask  ^ red);
 cout << "\n           mask ^ white = " << setw(8) <<
       (mask  ^ white);
 
unsigned long flags = 0xFF;        // Flags variable
 unsigned long bit1mask = 0x1;      // Selects bit 1
 
unsigned long bit6mask = 0x20;     // Selects bit 6
 
unsigned long bit20mask = 0x80000; // Selects bit 20
 cout << "\n\nNow use masks to select or set a particular
        flag bit.";
 
cout << "\nSelect bit 1 from flags : "   << setw(8) <<
       (flags & bit1mask);
 
cout << "\nSelect bit 6 from flags : "   << setw(8) <<
       (flags & bit6mask);
 
cout << "\nSwitch off bit 6 in flags : " << setw(8) <<
       (flags &= ~bit6mask);
 
cout << "\nSwitch on bit 20 in flags : " << setw(8) <<
       (flags |= bit20mask);
 
cout << endl;
 
return 0;
 
}

This example produces the following output:

======================================================

Try out bitwise AND and OR operators.
Initial value red          = 00ff0000
Complement ~red            = ff00ffff
Initial value white        = 00ffffff
Complement ~white          = ff000000
Bitwise AND red & white    = 00ff0000
Bitwise OR red | white     = 00ffffff
Now we can try out successive exclusive OR operations.
        mask = red ^ white = 0000ffff
                mask ^ red = 00ffffff
              mask ^ white = 00ff0000
Now use masks to select or set a particular flag bit.
Select bit 1 from flags    : 00000001
Select bit 6 from flags    : 00000020
Switch off bit 6 in flags  : 000000df
Switch on bit 20 in flags  : 000800df

====================================================

HOW IT WORKS

There is an #include directive for the <iomanip> standard header, which you saw in the last chapter, because the code uses manipulators to control the formatting of the output. To start with, you define two integer variables containing values representing the colors that you’ll use in subsequent bitwise operations:

 unsigned long red = 0XFF0000UL;      // Color red
 unsigned long white = 0XFFFFFFUL;    // Color white - RGB
      all maximum

You’ll want to display your data as hexadecimal values, so you specify this with this statement:

 cout << std::hex;         // Set hexadecimal output format

Here, hex is a manipulator that sets the output representation for integer values as hexadecimal. Note that this is modal—all subsequent integer output to the standard output stream in the program will now be in hexadecimal format. You don’t need to keep sending hex to the output stream, cout. If necessary, you could change back to decimal output with this statement:

 cout << std::dec;         // Set decimal output format

This uses the dec manipulator to reset integer output to the default decimal representation. Note that setting the output format to hexadecimal only affects integer values. Floating-point values will continue to be displayed in normal decimal form.

It would also make things clearer if you output your integers with leading zeros, and you set this mode with this statement:

 cout << setfill('0'); // Set fill character for output

Here, setfill() is a manipulator that sets the fill character to whatever character you put between the parentheses. This is also modal, so any subsequent integer output will use this fill character when necessary. Both decimal and hexadecimal output is affected. If you wanted asterisks instead, you would use this:

 cout << setfill('*');     // Set fill character for output

To set the fill character back to the default, you just use a space between the parentheses:

 cout << setfill(' ');     // Set fill character for output

The value of red and its complement are displayed by these statements:

 cout << "\nInitial value red     = " << setw(8) << red;
 cout << "\nComplement ~red       = " << setw(8) << ~red;

You use the setw() manipulator that you saw in the last chapter to set the output field width to 8. If you make sure all your output values will be in a field of the same width, it will be easier to compare them. Setting the width is not modal; it only applies to the output from the next statement that comes after the point at which the width is set. From the output for red and white, you can see that the ~ operator is doing what you expect: flipping the bits of its operand.

You combine red and white using the bitwise AND and OR operators with these statements:

 cout << "\n Bitwise AND  red & white = " << setw(8) << 
      (red & white);
 cout << "\n Bitwise OR   red | white = " << setw(8) <<
      (red | white);

Notice the parentheses around the expressions in the output. These are necessary because the precedence of << is higher than & and |. Without the parentheses, the statements wouldn’t compile. If you check the output, you’ll see that it’s precisely as discussed. The result of ANDing two bits is 1 if both bits are 1; otherwise the result is 0. When you bitwise-OR two bits, the result is 1 unless both bits are 0.

Next, you create a mask to use to flip between the values red and white by combining the two values with the exclusive OR operator:

 unsigned long mask = red ^ white;

If you inspect the output for the value of mask, you’ll see that the exclusive OR of two bits is 1 when the bits are different and 0 when they’re the same. By combining mask with either of the two color values using exclusive OR, you can obtain the other, as demonstrated by these statements:

 cout << "\n           mask ^ red = " << setw(8) << (mask 
       ^ red);
 cout << "\n         mask ^ white = " << setw(8) << (mask
       ^ white);

The last group of statements demonstrates how to use a mask to select a single bit from a group of flag bits. The mask to select a particular bit must have that bit as 1 and all other bits as 0. Thus, the masks to select bits 1, 6, and 20 from a 32-bit long variable are defined as follows:

 unsigned long bit1mask = 0x1;            // Selects bit 1
 unsigned long bit6mask = 0x20;           // Selects bit 6
 unsigned long bit20mask = 0x80000;       // Selects bit 20

To select a bit from flags, you just need to bitwise-AND the appropriate mask with the value of flags, for example:

cout << "\nSelect bit 6 from flags    : " << setw(8) <<
      (flags & bit6mask);

You can see from the output that the result of the expression (flags & bit6mask) is an integer with just bit 6 set. Of course, if bit 6 in flags was 0, the result of the expression would be 0.

To switch a bit off, you need to bitwise-AND the flags variable with a mask containing 0 for the bit you want to switch off and 1 everywhere else. You can easily produce this by applying the complement operator to a mask with the appropriate bit set, and bit6mask is just such a mask. The statement to switch off bit 6 in flags and display the result is as follows:

 cout << "\nSwitch off bit 6 in flags : " << setw(8) <<
       (flags &= ~bit6mask);

Of course, if bit 6 were already 0, it would remain as such. To switch a bit on, you just OR flags with a mask having the bit you want to switch on as 1:

 cout << "\nSwitch on bit 20 in flags : " << setw(8) <<
        (flags |= bit20mask);

This sets bit 20 of flags to 1 and displays the result. Again, if the bit were already 1, it would remain as 1.


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.


blog comments powered by Disqus
C++ ARTICLES

- Intel Threading Building Blocks
- Threading Building Blocks with C++
- Video Memory Programming in Text Mode
- More Tricks to Gain Speed in Programming Con...
- Easy and Efficient Programming for Contests
- Preparing For Programming Contests
- Programming Contests: Why Bother?
- Polymorphism in C++
- Overview of Virtual Functions
- Inheritance in C++
- Extending the Basic Streams in C++
- Using Stringstreams in C++
- Custom Stream Manipulation in C++
- General Stream Manipulation in C++
- Serialize Your Class into Streams in C++

Watch our Tech Videos 
Dev Articles Forums 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Contact Us 
Site Map 
Privacy Policy 
Support 

Developer Shed Affiliates

 




© 2003-2017 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap
Popular Web Development Topics
All Web Development Tutorials