Standard Library[lib]

C++ bitset: std::bitset explained with examples

Section
Standard Library [lib]
Standard
C++17
Compilers
MSVC 19.44, Clang 19.1 (MSVC STL), GCC 16.2, Clang 23.1 (libc++)
Published
Length
7 min read
In this answer7 clauses
  1. 1How do you create a bitset in C++?
  2. 2Why is bit 0 the rightmost bit?
  3. 3How do you set, reset, flip and test a bit?
  4. 4How do you count the bits that are set in a bitset?
  5. 5How do you convert a bitset to a string or a number?
  6. 6What do &, |, ^, ~ and the shifts do on a bitset?
  7. 7bitset, vector of bool or an unsigned integer: which one?

Abstract

A C++ bitset, std::bitset<N> from <bitset>, holds N bits, with N fixed in the type. Build it from a number or a string of 0s and 1s; set, reset, flip and test bits by position, bit 0 being the rightmost; count() gives the number of bits that are 1, to_string() the binary text and to_ulong() or to_ullong() the number. test() throws std::out_of_range for a bad position; b[pos] throws nothing and is not required to check.

Eight square cells in a row; the third, fifth and seventh from the left are solid blue. A dimension arrow spans the row above; below, an axis runs left from a dot under the rightmost cell.
Figure 1 — A fixed row of bits, some on and some off.

A C++ bitset, std::bitset<N> from <bitset>, is a fixed-size sequence of N bits, with N written in the type. You build one from a number or a string of 0s and 1s, then set, clear, flip and test single bits, count the bits that are on and print it in binary. Bit 0 is the rightmost bit when printed.

The smallest whole program puts 42 in eight bits, counts the bits that are on, turns on bit 0 and reads the number back:

[Example 1:
#include <bitset>
#include <iostream>

int main() {
    std::bitset<8> b(42);               // 42 in eight bits

    std::cout << b << '\n';             // prints 00101010
    std::cout << b.count() << '\n';     // bits that are 1: 3

    b.set(0);                           // turn on bit 0
    std::cout << b << '\n';             // prints 00101011
    std::cout << b.to_ulong() << '\n';  // back to a number: 43
}

— end example]

It printed:

[Example 2:
00101010
3
00101011
43

— end example]

The samples on this page are C++17, built with MSVC 19.44, Clang 19.1 (MSVC STL), GCC 16.2 and Clang 23.1 (libc++); where the four differed, the section says so. Since When lists which standard added each feature.

How do you create a bitset in C++?

Put the number of bits in the angle brackets, then give the bitset a number, a string of '0' and '1' characters, or nothing, which leaves every bit 0. N is a template argument, a constant fixed when the program is compiled, so a bitset cannot change size.

[Example 3:
std::bitset<8> empty;                 // every bit 0
std::bitset<8> from_number(42);
std::bitset<8> from_text("00101010");
std::bitset<8> short_text("110010");  // six characters for 8 bits
std::bitset<4> too_small(42);         // 42 needs six bits

— end example]

Printed, they read 00000000, 00101010, 00101010, 00110010 and 1010 on all four compilers. Three rules of the bitset constructors show in them:

  • A number is taken as an unsigned integer (unsigned long long), and bits that do not fit are dropped from the top, silently: too_small kept the low four bits of 42.
  • A string no longer than N puts its last character in bit 0, so a short string fills the low bits and the missing high bits are 0; a longer string keeps only its first N characters (std::bitset<4>("101100") is 1011).
  • A character other than 0 or 1 throws std::invalid_argument: std::bitset<8>("0012") threw it on all four.

Why is bit 0 the rightmost bit?

A bitset is numbered like a binary number: position 0 is the lowest bit, and printing writes the highest bit first. So b[0] is the last character of what std::cout << b shows:

[Example 4:
std::bitset<8> b(42);
std::cout << b << '\n';                  // 00101010

std::cout << "b[0] = " << b[0] << '\n';  // the last character
std::cout << "b[1] = " << b[1] << '\n';  // second from the right
std::cout << "b[7] = " << b[7] << '\n';  // the first character

— end example]

All four printed 00101010, then b[0] = 0, b[1] = 1 and b[7] = 0: bit 1 is the second character from the right.

The bitset for 42: eight boxes holding 0 0 1 0 1 0 1 0, the 1s in black, positions 7 to 0 beneath. Arrows mark the leftmost box bit 7, printed first, and the rightmost bit 0, printed last.
Figure 2 — Bit 0 is the rightmost bit: a bitset is numbered like a binary number, and printed highest bit first.

The shifts follow the same numbering: << moves bits toward higher positions, which is left as printed.

How do you set, reset, flip and test a bit?

Call set(pos) to turn a bit on, reset(pos) to turn it off, flip(pos) to switch it and test(pos) to read it; without an argument, set(), reset() and flip() change every bit. Here the bits are eight permission flags:

[Example 5:
const std::size_t can_read = 0;
const std::size_t can_write = 1;
const std::size_t is_admin = 7;

std::bitset<8> perms;           // eight permission flags, all off
perms.set(can_read);            // bit 0 on
perms.set(can_write);           // bit 1 on
std::cout << perms << '\n';     // 00000011

perms.reset(can_write);         // bit 1 off
perms.flip(is_admin);           // bit 7: off becomes on
std::cout << perms << '\n';     // 10000001

std::cout << perms.test(is_admin) << '\n';   // 1
std::cout << perms.test(can_write) << '\n';  // 0

perms.flip();                   // no argument: every bit
std::cout << perms << '\n';     // 01111110

try {
    std::cout << perms.test(8) << '\n';  // there is no bit 8
} catch (const std::out_of_range& e) {
    std::cout << "out_of_range\n";
    std::cout << e.what() << '\n';
}

— end example]

All four printed what the comments show, then out_of_range. The message what() returns differs from library to library, so catch the type, not the text. The standard has test, set(pos), reset(pos) and flip(pos) throw std::out_of_range for a position that is not a valid bit; on all four, set(8), reset(8) and flip(8) left perms as it was.

How do you count the bits that are set in a bitset?

count() returns how many bits are 1, as a std::size_t, and size() returns N, the number of bits. any(), none() and all() answer whether at least one bit, no bit or every bit is 1:

[Example 6:
void report(const std::bitset<8>& b) {
    std::cout << b
              << "  count " << b.count()
              << "  size " << b.size()
              << "  any " << b.any()
              << "  none " << b.none()
              << "  all " << b.all() << '\n';
}

— end example]

Called on three bitsets, with std::boolalpha on so the answers print as true and false, it printed the same on all four (size was 8 each time):

Bitset count() any() none() all()
00101010 (42) 3 true false false
00000000 0 false true false
11111111 8 true false true

How do you convert a bitset to a string or a number?

to_string() returns the bits as a std::string, highest bit first, and to_ulong() and to_ullong() return them as an unsigned long and an unsigned long long. To print an int in binary, go the other way: build a bitset from the int and call to_string().

[Example 7:
std::bitset<8> b(42);

std::string text = b.to_string();        // "00101010"
unsigned long n = b.to_ulong();          // 42
unsigned long long big = b.to_ullong();  // 42

std::cout << text << '\n';
std::cout << n << ' ' << big << '\n';
std::cout << b.to_string('.', '#') << '\n';  // your own 0 and 1

int value = 42;
std::cout << std::bitset<8>(value).to_string() << '\n';
std::cout << std::bitset<16>(value).to_string() << '\n';

int negative = -42;
std::cout << std::bitset<8>(negative).to_string() << '\n';

— end example]

It printed:

[Example 8:
00101010
42 42
..#.#.#.
00101010
0000000000101010
11010110

— end example]

The N you pick sets the width, and a negative int comes out as its two’s-complement bits, the usual binary form of a negative number: -42 gave 11010110 on all four.

to_ulong() throws std::overflow_error when the value does not fit in an unsigned long, and that type was 32 bits wide on the Windows builds and 64 on the Linux ones. A bitset<64> holding 4294967296 threw on Windows and printed the number on Linux. When the value may need more than 32 bits, call to_ullong(), which printed it on all four; it throws the same exception only for a value an unsigned long long cannot hold.

What do &, |, ^, ~ and the shifts do on a bitset?

They work bit by bit, like the bitwise operators on integers. & (and), | (or) and ^ (exclusive or) combine two bitsets of the same size, ~ flips every bit, and << and >> shift every bit, bringing in zeros and dropping the bits pushed off the end.

[Example 9:
std::bitset<8> a(42);           // 00101010
std::bitset<8> b("00001111");

std::cout << (a & b) << '\n';   // and: 1 where both are 1
std::cout << (a | b) << '\n';   // or: 1 where either is 1
std::cout << (a ^ b) << '\n';   // xor: 1 where they differ
std::cout << ~a << '\n';        // not: every bit flipped
std::cout << (a << 2) << '\n';  // zeros come in on the right
std::cout << (a >> 2) << '\n';  // zeros come in on the left

— end example]

All four printed:

Expression Printed
a & b 00001010
a | b 00101111
a ^ b 00100101
~a 11010101
a << 2 10101000
a >> 2 00001010

Both sides must have the same N: a & b with a bitset<8> and a bitset<16> did not compile on any of the four. The forms &=, |=, ^=, <<= and >>= change the left bitset in place.

bitset, vector of bool or an unsigned integer: which one?

Pick by when you know the number of bits and what you do with them:

When Use
The size is fixed as you write the code, and you want named operations and printing std::bitset<N>
The size is known only when the program runs std::vector<bool>, or boost::dynamic_bitset
A handful of flags to pass to an API or store compactly an unsigned integer, with a named constant (a mask) per bit

The other containers and utilities are in Standard library.

Questions

How do you convert an int to binary in C++?

Build a bitset from it: std::cout << std::bitset<8>(n) prints the eight lowest bits of n, and std::bitset<8>(n).to_string() returns them as a string. N sets the width: std::bitset<32>(n) gives every bit of an int, which was 32 bits on all four. A negative int comes out as its two’s-complement bits, so -42 in eight bits gave 11010110.

How do you convert a bitset to a string?

Call to_string(). It returns a std::string of N characters, the highest bit first and bit 0 last, so std::bitset<8>(42).to_string() is “00101010″. Two optional arguments choose the characters for 0 and 1: to_string(‘.’, ‘#’) gave “..#.#.#.”.

What is the difference between bitset and vector of bool?

A std::bitset has its number of bits fixed in its type, chosen when the code is compiled. A std::vector<bool> chooses its size while the program runs and can grow, and how it packs its bits is up to the implementation. Use bitset when you know the number of bits as you write the code, vector<bool> when it comes from input.

Can the size of a bitset be set at run time?

No. N is a template argument, so it must be a constant the compiler knows, and it cannot change after the bitset is made. For a size known only at run time, use std::vector<bool> or boost::dynamic_bitset.

What does bitset count return?

The number of bits that are 1, as a std::size_t: std::bitset<8>(42).count() is 3, since 42 is 00101010. For the total number of bits, call size(), which returns N.

Which header is std::bitset in?

Include <bitset>, the standard header that declares std::bitset. The <bits/stdc++.h> that some tutorials include is not a standard header, so include <bitset> itself.

Sources

  1. std::bitsetcppreference.com
  2. std::bitset::bitsetcppreference.com
  3. std::bitset::testcppreference.com
  4. std::bitset::countcppreference.com
  5. std::bitset::to_stringcppreference.com
  6. std::bitset::to_ulongcppreference.com
  7. [template.bitset] Class template bitsetC++ standard working draft

Read next

  1. std::swap in C++: how to swap two values, with examplesStandard Library · Miriam Castellanos · written for C++17
  2. Stack in C++: how std::stack works, with examplesStandard Library · Miriam Castellanos · written for C++17
  3. std::array in C++: how to declare and use oneStandard Library · Miriam Castellanos · written for C++17