Do you think IIT Guwahati certified course can help you in your career?
No
Introduction
A bitset is a sequence that represents bit values as 0s and 1s. This structure is highly efficient for performing bitwise operations in programming. Bitset is a class in the C++ Standard Template Library (STL). It allows you to manipulate individual bits and perform bitwise operations efficiently. Bitset optimizes space usage by packing bits into a compact storage format.
In this article, we'll discuss the basics of bitset, its syntax, member functions, operators, and key differences from other boolean containers like vector<bool> and bool arrays.
Syntax
To create a bitset in C++, you use the std::bitset class template. The template takes an integer argument N that specifies the number of bits in the set. The basic syntax is:
std::bitset<N> bs;
For example, to create a bitset with 8 bits, you would write:
std::bitset<8> bs;
You can also initialize the bitset with a binary string or an integer value. For example:
std::bitset<8> bs1("10101010"); // initialize with binary string
std::bitset<8> bs2(42); // initialize with integer value
In the first example, bs1 is initialized with the binary string "10101010", so the bits are set to 1, 0, 1, 0, 1, 0, 1, 0. In the second example, bs2 is initialized with the integer value 42, which is 00101010 in binary, so the bits are set accordingly.
Note: You can access and modify individual bits using the [] operator or the set(), reset(), and flip() member functions
std::bitset Member Functions
The std::bitset class provides several useful member functions for manipulating & querying the bits in the set. Some of the most commonly used ones are:
test(pos): Returns true if the bit at position pos is set (1), false otherwise.
set(pos, val = true): Sets the bit at position pos to val (default is 1).
reset(pos): Resets the bit at position pos to 0.
flip(pos): Flips the bit at position pos (0 becomes 1, 1 becomes 0).
all(): Returns true if all bits are set, false otherwise.
any(): Returns true if at least one bit is set, false otherwise.
none(): Returns true if no bits are set, false otherwise.
count(): Returns the number of bits that are set.
size(): Returns the total number of bits in the bitset.
to_string(): Returns a string representation of the bitset.
to_ulong(): Returns an unsigned long integer representation of the bitset.
to_ullong(): Returns an unsigned long long integer representation of the bitset.
In this example, we create a bitset bs with the binary string "10101010." We then print out the bitset and the number of set bits (4) and test the first two bits. We flip all the bits using flip(), set all the bits using set(), and print out the modified bitset each time.
std::bitset operators
std::bitset Operators
The std::bitset class overloads several operators to make it easy to perform bitwise operations & comparisons on bitsets. Here are the most commonly used ones:
1. &: Bitwise AND operator. Returns a new bitset that is the bitwise AND of the operands.
2. |: Bitwise OR operator. Returns a new bitset that is the bitwise OR of the operands.
3. ^: Bitwise XOR operator. Returns a new bitset that is the bitwise XOR of the operands.
4. ~: Bitwise NOT operator. Returns a new bitset that is the bitwise complement of the operand.
5. <<: Left shift operator. Shifts the bits in the bitset to the left by the specified number of positions.
6. >>: Right shift operator. Shifts the bits in the bitset to the right by the specified number of positions.
7. ==, !=: Equality & inequality operators. Return true if the bitsets are equal/not equal, false otherwise.
In this example, we create two bitsets bs1 & bs2, & perform various bitwise operations on them using the overloaded operators. We print out the results of each operation to see how they work.
The bitwise AND, OR & XOR operators (&, |, ^) return new bitsets that are the result of applying the corresponding operation to each pair of bits in the operands. The bitwise NOT operator (~) returns a new bitset that is the complement of the operand (0s become 1s & vice versa).
The left & right shift operators (<<, >>) shift the bits in the bitset by the specified number of positions, filling in with 0s. The equality, inequality & comparison operators (==, !=, <, <=, >, >=) compare the bitsets lexicographically, i.e., by comparing the bits from left to right.
Difference between std::bitset and std::vector<bool> and an array of bool
Parameters
std::bitset
std::vector<bool>
Array of bool
Storage
std::bitset stores bits in a compact, fixed-size sequence, using just enough space to hold the specified number of bits. This makes it memory-efficient for representing fixed-size collections of bits.
std::vector<bool> is a specialization of std::vector that packs bits into memory, but it still uses more memory than std::bitset due to the dynamic nature of std::vector.
An array of bool stores each boolean value as a separate byte, resulting in wasted memory compared to std::bitset or std::vector<bool>. This makes it less memory-efficient for storing large collections of bits.
Size
The size of an std::bitset is fixed at compile-time and cannot be changed during runtime. This can be advantageous when you know the exact number of bits needed and want to avoid dynamic memory allocation.
std::vector<bool> can be resized dynamically during runtime, providing flexibility when the number of bits needed is not known at compile-time or may change during program execution.
The size of an array of bool is fixed at compile-time and cannot be changed during runtime, similar to std::bitset. However, the size is determined by the number of elements rather than the number of bits.
Performance
std::bitset provides the best performance for bitwise operations and individual bit access due to its compact storage and optimized member functions. It is the preferred choice when performance is critical.
std::vector<bool> offers good performance for bitwise operations and individual bit access, but it may be slightly slower than std::bitset due to its dynamic nature and the overhead of maintaining a vector.
An array of bool has the worst performance for bitwise operations and individual bit access because it stores each bit as a separate byte, resulting in increased memory usage and slower access times.
Functionality
std::bitset provides a rich set of member functions for manipulating and querying bits, making it convenient to perform common bitwise operations and checks.
std::vector<bool> supports the standard std::vector operations, such as resizing, pushing back elements, and iterating over the bits. However, it lacks some of the specialized bitwise operations provided by std::bitset.
An array of bool is a basic C-style array and does not provide any specialized member functions for bitwise operations. You would need to write your own functions or use loops to manipulate and query the bits.
Ease of Use
std::bitset is easy to use for fixed-size collections of bits and provides a clean and readable syntax for bitwise operations. The template argument specifying the number of bits can make the code more expressive.
std::vector<bool> is easy to use if you are already familiar with std::vector and need a dynamically resizable collection of bits. However, the syntax for bitwise operations may be less intuitive compared to std::bitset.
An array of bool is straightforward to use if you are comfortable with C-style arrays and don't require specialized bitwise operations. However, the code may be more verbose and less expressive compared to std::bitset or std::vector<bool>.
Frequently Asked Questions
Can std::bitset be resized during runtime?
No, the size of std::bitset is fixed at compile-time and cannot be changed during runtime.
Is std::vector<bool> more memory-efficient than an array of bool?
Yes, std::vector<bool> is more memory-efficient than an array of bool because it packs bits into memory, while an array of bool stores each boolean value as a separate byte.
Which container provides the best performance for bitwise operations?
std::bitset provides the best performance for bitwise operations due to its compact storage and optimized member functions.
Conclusion
In this article, we discussed the std::bitset class in C++, which provides an efficient way to store and manipulate fixed-size sequences of bits. We covered the syntax, member functions, and operators of std::bitset, and provided examples to show its implementation. We also compared std::bitset with std::vector<bool> and arrays of bool, discussing their differences in storage, size, performance, functionality, and ease of use.