Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com
Answertopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions
Privacy Policy

  




 

 

Thinking in C++ Vol 2 - Practical Programming
Prev Home Next

bitset<n>

The template for bitset accepts an unsigned integral template argument that is the number of bits to represent. Thus, bitset<10> is a different type than bitset<20>, and you cannot perform comparisons, assignments, and so on between the two.

A bitset provides the most commonly used bitwise operations in an efficient form. However, each bitset is implemented by logically packing bits in an array of integral types (typically unsigned longs, which contain at least 32 bits). In addition, the only conversion from a bitset to a numerical value is to an unsigned long (via the function to_ulong( )).

The following example tests almost all the functionality of the bitset (the missing operations are redundant or trivial). You ll see the description of each of the bitset outputs to the right of the output so that the bits all line up and you can compare them to the source values. If you still don t understand bitwise operations, running this program should help.

//: C07:BitSet.cpp {-bor}
// Exercising the bitset class.
#include <bitset>
#include <climits>
#include <cstdlib>
#include <ctime>
#include <cstddef>
#include <iostream>
#include <string>
using namespace std;
 
const int SZ = 32;
typedef bitset<SZ> BS;
 
template<int bits> bitset<bits> randBitset() {
bitset<bits> r(rand());
for(int i = 0; i < bits/16 - 1; i++) {
r <<= 16;
// "OR" together with a new lower 16 bits:
r |= bitset<bits>(rand());
}
return r;
}
 
int main() {
srand(time(0));
cout << "sizeof(bitset<16>) = "
<< sizeof(bitset<16>) << endl;
cout << "sizeof(bitset<32>) = "
<< sizeof(bitset<32>) << endl;
cout << "sizeof(bitset<48>) = "
<< sizeof(bitset<48>) << endl;
cout << "sizeof(bitset<64>) = "
<< sizeof(bitset<64>) << endl;
cout << "sizeof(bitset<65>) = "
<< sizeof(bitset<65>) << endl;
BS a(randBitset<SZ>()), b(randBitset<SZ>());
// Converting from a bitset:
unsigned long ul = a.to_ulong();
cout << a << endl;
// Converting a string to a bitset:
string cbits("111011010110111");
cout << "as a string = " << cbits <<endl;
cout << BS(cbits) << " [BS(cbits)]" << endl;
cout << BS(cbits, 2) << " [BS(cbits, 2)]" << endl;
cout << BS(cbits, 2, 11) << " [BS(cbits, 2, 11)]"<< endl;
cout << a << " [a]" << endl;
cout << b << " [b]" << endl;
// Bitwise AND:
cout << (a & b) << " [a & b]" << endl;
cout << (BS(a) &= b) << " [a &= b]" << endl;
// Bitwise OR:
cout << (a | b) << " [a | b]" << endl;
cout << (BS(a) |= b) << " [a |= b]" << endl;
// Exclusive OR:
cout << (a ^ b) << " [a ^ b]" << endl;
cout << (BS(a) ^= b) << " [a ^= b]" << endl;
cout << a << " [a]" << endl; // For reference
// Logical left shift (fill with zeros):
cout << (BS(a) <<= SZ/2) << " [a <<= (SZ/2)]" << endl;
cout << (a << SZ/2) << endl;
cout << a << " [a]" << endl; // For reference
// Logical right shift (fill with zeros):
cout << (BS(a) >>= SZ/2) << " [a >>= (SZ/2)]" << endl;
cout << (a >> SZ/2) << endl;
cout << a << " [a]" << endl; // For reference
cout << BS(a).set() << " [a.set()]" << endl;
for(int i = 0; i < SZ; i++)
if(!a.test(i)) {
cout << BS(a).set(i)
<< " [a.set(" << i <<")]" << endl;
break; // Just do one example of this
}
cout << BS(a).reset() << " [a.reset()]"<< endl;
for(int j = 0; j < SZ; j++)
if(a.test(j)) {
cout << BS(a).reset(j)
<< " [a.reset(" << j <<")]" << endl;
break; // Just do one example of this
}
cout << BS(a).flip() << " [a.flip()]" << endl;
cout << ~a << " [~a]" << endl;
cout << a << " [a]" << endl; // For reference
cout << BS(a).flip(1) << " [a.flip(1)]"<< endl;
BS c;
cout << c << " [c]" << endl;
cout << "c.count() = " << c.count() << endl;
cout << "c.any() = "
<< (c.any() ? "true" : "false") << endl;
cout << "c.none() = "
<< (c.none() ? "true" : "false") << endl;
c[1].flip(); c[2].flip();
cout << c << " [c]" << endl;
cout << "c.count() = " << c.count() << endl;
cout << "c.any() = "
<< (c.any() ? "true" : "false") << endl;
cout << "c.none() = "
<< (c.none() ? "true" : "false") << endl;
// Array indexing operations:
c.reset();
for(size_t k = 0; k < c.size(); k++)
if(k % 2 == 0)
c[k].flip();
cout << c << " [c]" << endl;
c.reset();
// Assignment to bool:
for(size_t ii = 0; ii < c.size(); ii++)
c[ii] = (rand() % 100) < 25;
cout << c << " [c]" << endl;
// bool test:
if(c[1])
cout << "c[1] == true";
else
cout << "c[1] == false" << endl;
} ///:~
 

To generate interesting random bitsets, the randBitset( ) function is created. This function demonstrates operator<<= by shifting each 16 random bits to the left until the bitset (which is templatized in this function for size) is full. The generated number and each new 16 bits are combined using the operator|=.

The main( ) function first shows the unit size of a bitset. If it is less than 32 bits, sizeof produces 4 (4 bytes = 32 bits), which is the size of a single long on most implementations. If it s between 32 and 64, it requires two longs, greater than 64 requires 3 longs, and so on. Thus, you make the best use of space if you use a bit quantity that fits in an integral number of longs. However, notice there s no extra overhead for the object it s as if you were hand-coding for a long.

Although there are no other numerical conversions from bitset besides to_ulong( ), there is a stream inserter that produces a string containing ones and zeros, and this can be as long as the actual bitset.

There s still no primitive format for binary values, but bitset supports the next best thing: a string of ones and zeros with the least-significant bit (lsb) on the right. The three constructors demonstrated take the entire string, the string starting at character 2, and the string from character 2 through 11. You can write to an ostream from a bitset using operator<<, and it comes out as ones and zeros. You can also read from an istream using operator>> (not shown here).

You ll notice that bitset only has three nonmember operators: and (&), or (|), and exclusive-or (^). Each of these creates a new bitset as its return value. All the member operators opt for the more efficient &=, |=, and so on, where a temporary is not created. However, these forms change the bitset s value (which is a in most of the tests in the above example). To prevent this, we created a temporary to be used as the lvalue by invoking the copy-constructor on a; this is why you see the form BS(a). The result of each test is displayed, and occasionally a is reprinted so you can easily look at it for reference.

The rest of the example should be self-explanatory when you run it; if not you can find the details in your compiler s documentation or in the other documentation mentioned earlier in this chapter.

Thinking in C++ Vol 2 - Practical Programming
Prev Home Next

 
 
   Reproduced courtesy of Bruce Eckel, MindView, Inc. Design by Interspire