Bitset Operations and Access
A bitset is a fixed-size collection of bits.
Why a Bitset Needs Starting Values
A bitset is a fixed-size collection of bits. Before you can use one, you need to give it starting values, and C++ offers more than one way to do that. The source material for this lesson states that a bitset can be initialized with an integer or a string. Both forms use the same brace-based declaration style, so the main thing to learn is which kind of value goes inside the braces and what that value means for the bits that end up stored.
What do you think happens?
Before reading on: if you declare bitset<9> bs1 {"110001111"}; and bitset<9> bs2 {399};, do you think the two bitsets hold the same bits, or different bits?
Reveal answer
The same bits. The integer 399 corresponds to the bit pattern 110001111, which is the same nine-character string.
The quotes decide whether the value is read as text or as a number, but they do not change the bits that result when the text and the number describe the same pattern. The rest of this article explains how each form produces its bits.
The lesson follows a simple rhythm: work out what the code should produce, then trace the mechanism that actually produces the bits. Keep the prediction above in mind, because the next sections show exactly how a string and an integer each become a bit pattern.
Reading the Declaration Syntax
A bitset declaration names its size in angle brackets and gives the initial value in braces. The general pattern is bitset<N> bs {value};, where N is the number of bits and value is the initial value you supply. The angle-bracket part controls how many bits the bitset has. The variable name, here bs, is the name you use to refer to the bitset later. The brace-enclosed value controls the starting bits.
The size N is part of the type, so bitset<9> and bitset<8> are different types. A bitset declared with N = 9 always has exactly nine bits, whatever value you pass in. The value inside the braces decides which starting bits those nine positions receive. The source material notes that a bitset can be initialized with different constructors, and that the kind of argument you choose decides which constructor is used.
Tracing a String Initialization
When the value inside the braces is a string literal, the bitset is built from the characters of that string. The string is enclosed in double quotes, which marks it as text rather than a number. In the source example, bitset<9> bs1 {"110001111"}; passes a nine-character string made of 0 and 1 characters. Nine characters fill nine bits, so every character has a bit position to land in.
Reading bs1 position by position
Given bitset<9> bs1 {"110001111"};, which bit holds the rightmost character, and what value does it have?
- 1Identify the rightmost character
The string is 110001111, and its last character is 1.
- 2Assign it to bit 0
The rightmost character corresponds to the lowest bit position, bit 0.
- 3Check the result
Bit 0 holds 1, which matches the rightmost character of the string.
Bit 0 of bs1 is 1. Reading the string right to left gives bits 0 through 8 as 1, 1, 1, 1, 0, 0, 0, 1, 1.
Tracing an Integer Initialization
When the value inside the braces is an integer, the bitset is built from that number. The source example bitset<9> bs2 {399}; uses an integer literal with no quotes. There is no separate string conversion step in the code, because the value is already a number. The integer form is useful when your starting value is already a number, such as a computed result or a constant.
The expansion above shows where the bit pattern comes from. The powers 28 and 27 contribute to bits 8 and 7, and the powers 23, 22, 21, and 20 contribute to bits 3, 2, 1, and 0. The remaining bits 6, 5, and 4 are 0. Reading those nine positions from left to right gives 110001111, which is the same pattern as the string in the previous section.
Size Mismatch and Padding
The size N is fixed by the angle-bracket value, so the bitset always has exactly that many bits. What happens when the starting value has a different number of bits than N is an important check. If the value has fewer bits than N, the bits that the value does not supply are zero. For example, the four-character string "1011" placed in an eight-bit bitset fills the four low positions, and the four high positions stay 0. If the integer has more significant bits than N can hold, the bits beyond position N minus 1 are not kept, so bitset<8> {399} keeps only the low eight bits of 399.
Because N is part of the declaration, a mismatch between the value and N is a common source of unexpected bit patterns. When you check an initialization, compare the number of bits the value actually supplies with the N you declared.
Comparing Two Initializations Position by Position
Two differently initialized bitsets hold the same bit pattern when every index has the same value in both. You can check this position by position: write down the bits of each bitset from bit N minus 1 down to bit 0, then compare the two lists. If every position matches, the bitsets hold the same pattern, even though the initial values were written in different forms.
a and b hold the bit pattern 00001011 at every index- a is built from the string 1011, which is 11 in binary
- b is built from the integer 11, which is 1011 in binary
- Both declarations use N = 8, so both have eight positions
What do you think happens?
Given bitset<8> a {"1011"}; and bitset<8> b {11};, do a and b hold identical bits at every index?
Reveal answer
Yes, at every index. Both hold 00001011, with bit 0 equal to 1, bit 1 equal to 1, bit 2 equal to 0, bit 3 equal to 1, and bits 4 through 7 equal to 0.
The string 1011 and the integer 11 describe the same binary number, and both declarations use the same size of eight. The argument form changes the constructor used, not the pattern.
Mistakes in Initialization
When two declarations that should match do not, the mismatch points to one of three places: the value you passed, the size you declared, or the constructor form you chose. Check each of these in turn.
Common mistake Leaving out the quotes around a bit string
What it looks likebitset<9> bs {110001111};Why it failsQuotes decide whether a value is read as text or as a number. Without quotes, 110001111 is read as a decimal integer, which is a different number from the pattern 110001111 in binary.
Do this insteadWrite bitset<9> bs {"110001111"}; when you mean the bit string, and write bitset<9> bs {399}; when you mean the number.
Common mistake Declaring a size that does not match the value
What it looks likebitset<8> bs {399};Why it failsThe integer has more significant bits than the eight positions N can hold, so the high bit that gives 399 its value is not kept.
Do this insteadCheck that the bits the value needs fit within N, or choose a larger N.
Common mistake Assuming the string and integer forms always produce the same bits
What it looks likebitset<8> a {"1011"}; bitset<8> b {1011};Why it failsThe second declaration uses the decimal integer 1011, not the binary pattern 1011, so the two bitsets hold different bits.
Do this insteadUse the integer 11 when you mean the pattern 1011, or use the string "1011" when you want the literal bits.
Common mistake Changing the declared size without rechecking the value, so the same brace-enclosed value now produces a different pattern
Practicing Bit Pattern Predictions
Without running the code, decide whether bitset<8> x {"0110"}; and bitset<8> y {6}; hold the same bits at every index. Write down the bit at index 0 and the bit at index 2 for each bitset, then justify your answer.
Hints
- Convert the integer 6 to binary first. Which bits does 6 set?
- The string 0110 has four characters, so the rightmost character sits at index 0.
- Compare index 0 and index 2 before checking the other positions.
Declare bitset<9> with the string value that matches bs2 {399}; in the source example, then explain why the declaration with a missing pair of quotes would produce a different bit pattern.
Hints
- The string value that matches 399 is 110001111.
- Without quotes, the braces read the digits as a decimal integer, so the value changes.
Key Takeaways
- A bitset is declared as bitset<N> bs {value};, where N is the number of bits and N is part of the type.
- A string value in double quotes, such as "110001111", fills the bits from the rightmost character at index 0 upward.
- An integer value with no quotes, such as 399, produces a bit pattern; here 399 corresponds to 110001111, the same bits as the string form.
- Two initializations hold the same pattern when every index matches, and mismatches usually come from the value passed, the size declared, or the constructor form chosen.