C++ bitset | "Bit Set" Guide
이 글의 핵심
It covers operations on the fixed-size bit set bitset, selection with vector<bool>, and masking/subset practice patterns.
What is bitset?
std::bitset is an STL container representing a fixed-size bitset. It allows efficient storage and manipulation of data bit by bit, and is useful for flags, state management, bit masks, etc.```cpp
#include
std::bitset<8> bits; // 8비트
bits.set(0); // 0번 비트 1 bits.set(3); // 3번 비트 1 bits.reset(0); // 0번 비트 0
- Memory efficiency: 1 bit = 1 bool (normal array is 1 byte)
- Bit operations: Intuitive operations such as AND, OR, XOR, NOT, etc.
- Type safety: compile-time size verification
- Convenience: Provides bit manipulation functions```cpp
// ❌ 일반 배열: 8바이트
bool flags[8] = {false};
// ✅ bitset: 1바이트
std::bitset<8> flags; // 8비트 = 1바이트
```Bit Indexing:```cpp
std::bitset<8> bits{"10101010"};
// 76543210 (인덱스)
std::cout << bits[0] << '\n'; // 0 (오른쪽)
std::cout << bits[7] << '\n'; // 1 (왼쪽)
// 주의: 문자열과 인덱스 방향이 반대!
```## Default use```cpp
#include <bitset>
// 생성
std::bitset<8> b1; // 00000000
std::bitset<8> b2{0b10101010}; // 10101010
std::bitset<8> b3{"10101010"}; // 10101010
// 접근
bool bit0 = b2[0];
bool bit7 = b2[7];
// 출력
std::cout << b2 << std::endl; // 10101010
```## Practical example
### Example 1: Flags```cpp
#include <bitset>
enum Permission {
Read = 0,
Write = 1,
Execute = 2,
Delete = 3
};
class FilePermissions {
std::bitset<4> perms;
public:
void grant(Permission p) {
perms.set(p);
}
void revoke(Permission p) {
perms.reset(p);
}
bool has(Permission p) const {
return perms[p];
}
void print() const {
std::cout << "읽기: " << perms[Read] << std::endl;
std::cout << "쓰기: " << perms[Write] << std::endl;
std::cout << "실행: " << perms[Execute] << std::endl;
std::cout << "삭제: " << perms[Delete] << std::endl;
}
};
int main() {
FilePermissions fp;
fp.grant(Read);
fp.grant(Write);
if (fp.has(Read)) {
std::cout << "읽기 가능" << std::endl;
}
fp.print();
}
```### Example 2: Bitwise operations```cpp
#include <bitset>
int main() {
std::bitset<8> b1{"11110000"};
std::bitset<8> b2{"10101010"};
// AND
auto and_result = b1 & b2;
std::cout << "AND: " << and_result << std::endl; // 10100000
// OR
auto or_result = b1 | b2;
std::cout << "OR: " << or_result << std::endl; // 11111010
// XOR
auto xor_result = b1 ^ b2;
std::cout << "XOR: " << xor_result << std::endl; // 01011010
// NOT
auto not_result = ~b1;
std::cout << "NOT: " << not_result << std::endl; // 00001111
}
```### Example 3: Transformation```cpp
#include <bitset>
std::bitset<8> bits{"10101010"};
// 정수로
unsigned long ul = bits.to_ulong();
std::cout << "정수: " << ul << std::endl; // 170
// 문자열로
std::string str = bits.to_string();
std::cout << "문자열: " << str << std::endl; // 10101010
// 정수에서
std::bitset<8> bits2{170};
```### Example 4: Count```cpp
#include <bitset>
std::bitset<8> bits{"10101010"};
// 1의 개수
std::cout << "1의 개수: " << bits.count() << std::endl; // 4
// 크기
std::cout << "크기: " << bits.size() << std::endl; // 8
// 모두 1?
std::cout << "모두 1: " << bits.all() << std::endl; // false
// 하나라도 1?
std::cout << "하나라도 1: " << bits.any() << std::endl; // true
// 모두 0?
std::cout << "모두 0: " << bits.none() << std::endl; // false
```## Bit operations```cpp
std::bitset<8> bits;
// 설정
bits.set(); // 모두 1
bits.set(3); // 3번 비트 1
bits.set(3, 0); // 3번 비트 0
// 리셋
bits.reset(); // 모두 0
bits.reset(3); // 3번 비트 0
// 플립
bits.flip(); // 모두 반전
bits.flip(3); // 3번 비트 반전
// 테스트
bool bit3 = bits.test(3);
```## Bit operation basics
A summary of frequently used operations in integers or `bitset` is as follows.
| operations | meaning | Example Intuition |
|------|------|-------|
| AND `&` | Only positions where both are 1 | Extract only specific bits with mask |
| OR (bitwise OR) | If even one is 1, then 1 | Beat On |
| XOR `^` | If they are different, 1 | Toggle, Compare for equality |
| NOT `~` | Everything is reversed | Flip entire mask |
| `<<` / `>>` | Shift left/right | \(2^k\) Movement corresponding to multiplication and division |
`std::bitset` overloads the above operation for the entire bit set, so AND/OR/XOR/NOT can be performed at once without a loop. Unlike integers, operations between bitsets of different sizes must have the same size at compile time.```cpp
std::bitset<8> a{"11001100"};
std::bitset<8> b{"10101010"};
std::bitset<8> low4 = a & std::bitset<8>{"00001111"}; // 하위 4비트만
```## bitset vs vector<bool>
Both aim for bit-wise compression, but their roles are different.
| Item | `std::bitset<N>` | `std::vector<bool>` |
|------|------------------|----------------------|
| size | Compile-time constant N (template argument) | `resize` possible at runtime |
| Save location | Fixed size, usually inside a stack or object | dynamic allocation on heap |
| operations | Rich bit operations such as AND·OR·XOR·NOT and shift | Element-specific approach/focus on some algorithms |
| Standard Guarantee | complete bit set type | Due to the specialization of `vector`, details such as references are difficult |
What to use and when
- If N is fixed in the code (e.g. 64 bits for flags, 32 bits for IPv4 mask), `bitset<N>` is type safe and the operation is clear.
- If the length changes depending on user input or file size, consider alternatives such as `vector<bool>` or `boost::dynamic_bitset` if the bit length is very large.
- Note in the documentation that `vector<bool>` is a “collection of bools” and not theoretically equivalent to the full `vector<T>` (e.g. `std::vector<bool>::reference`).
## Bit masking pattern
Turn on/off/toggle specific bits```cpp
unsigned x = 0b1010;
unsigned mask = 1u << 3; // 3번 비트
x |= mask; // 켜기
x &= ~mask; // 끄기
x ^= mask; // 토글
```In `bitset`, you can do the same thing more readably with `set(pos)`, `reset(pos)`, and `flip(pos)`.
Keep only low-order k bits: `x & ((1u << k) - 1)`
Extract specific section bits: Combine shift and AND.```cpp
std::bitset<16> v{"1111000011110000"};
auto low8 = (v & std::bitset<16>{"0000000011111111"}); // 개념적으로 하위 8비트
```## Practice: Flag management, permutation, combination
### Flag combination
The pattern of putting multiple options in one integer or `bitset` and passing them as bitwise OR is common in API flags.```cpp
enum class Opt : unsigned { A = 1u << 0, B = 1u << 1, C = 1u << 2 };
unsigned f = static_cast<unsigned>(Opt::A) | static_cast<unsigned>(Opt::C);
bool hasB = (f & static_cast<unsigned>(Opt::B)) != 0;
```Writing option indices directly with `bitset` makes the binary output clearer when debugging.
### Subset enumeration (bit mask)
Any subset of the set with elements \(0..n-1\) can be traversed with a mask from `0` to `2^n - 1`.```cpp
#include <bitset>
#include <iostream>
int main() {
const int n = 4;
// n이 크면 (1u << n) 오버플로에 주의 (unsigned 비트 폭 이하로 사용)
for (unsigned mask = 0; mask < (1u << n); ++mask) {
std::bitset<n> bs(mask);
std::cout << bs << '\n';
}
}
```When \(n\) is large, `2^n` explodes, so use backtracking or next subset optimization (e.g. `submask = (submask - 1) & mask`) as appropriate.
### Relationship between combination and permutation
- Combination: It is natural to use the position where the bit is 1 as the “selected element.”
- Permutation: Since the order is important, bits alone are not enough and are often used together with `next_permutation`, etc. However, the `bitset`/`uint32_t` mask appears frequently in State Compression DP, which sets “use or not” as a bit.
## Performance optimization
- Fixed size·Hot loop: The single operation of `bitset<N>` is good for the compiler to optimize word by word. If N is small, put it on the stack and avoid repeated allocations.
- Count: You can find the number of 1s at once with `count()`. When traversing specific bits, index loops and `test(i)` are standard methods, and when very fast least significant bit traversal is required, integer masks and compiler built-in functions (e.g. GCC `__builtin_ctzll`) are reviewed to suit project policy.
- I/O: `to_string()` iterations can be expensive when printing in bulk. If it is not for debugging, consider handling it with integer bit operations or writing the buffer all at once.
- vector<bool> vs bitset: If you don't really need dynamic sizes, `bitset` is often simpler in layout and easier to optimize.
## Frequently occurring problems
### Problem 1: Size```cpp
// 컴파일 타임 크기
std::bitset<8> bits;
// ❌ 런타임 크기
// int n = 8;
// std::bitset<n> bits; // 에러
// ✅ 런타임 크기: vector<bool>
std::vector<bool> bits(n);
```### Problem 2: Index```cpp
std::bitset<8> bits{"10101010"};
// 인덱스 0: 오른쪽 비트
std::cout << bits[0] << std::endl; // 0 (오른쪽)
std::cout << bits[7] << std::endl; // 1 (왼쪽)
```### Problem 3: Conversion```cpp
std::bitset<64> bits{0xFFFFFFFFFFFFFFFF};
// ❌ 오버플로우
// unsigned long ul = bits.to_ulong(); // 32비트 시스템에서 에러
// ✅ unsigned long long
unsigned long long ull = bits.to_ullong();
```### Problem 4: String```cpp
// 문자열 생성
std::bitset<8> bits{"10101010"};
// ❌ 잘못된 문자
// std::bitset<8> bits2{"102"}; // 예외
// ✅ 유효성 검사
try {
std::bitset<8> bits3{"10201010"};
} catch (const std::invalid_argument&) {
std::cout << "유효하지 않은 문자" << std::endl;
}
```## Practice pattern
### Pattern 1: State Machine```cpp
enum class State {
Idle = 0,
Running = 1,
Paused = 2,
Error = 3
};
class StateMachine {
std::bitset<4> activeStates_;
public:
void enterState(State s) {
activeStates_.set(static_cast<int>(s));
}
void exitState(State s) {
activeStates_.reset(static_cast<int>(s));
}
bool isInState(State s) const {
return activeStates_[static_cast<int>(s)];
}
bool isIdle() const {
return activeStates_.none(); // 모든 비트 0
}
};
// 사용
StateMachine sm;
sm.enterState(State::Running);
if (sm.isInState(State::Running)) {
std::cout << "실행 중\n";
}
```### Pattern 2: Set operations```cpp
class CharSet {
std::bitset<256> chars_; // ASCII 문자 집합
public:
void add(char c) {
chars_.set(static_cast<unsigned char>(c));
}
bool contains(char c) const {
return chars_[static_cast<unsigned char>(c)];
}
CharSet operator&(const CharSet& other) const {
CharSet result;
result.chars_ = chars_ & other.chars_;
return result;
}
CharSet operator|(const CharSet& other) const {
CharSet result;
result.chars_ = chars_ | other.chars_;
return result;
}
size_t size() const {
return chars_.count();
}
};
// 사용
CharSet vowels;
vowels.add('a'); vowels.add('e'); vowels.add('i');
CharSet consonants;
consonants.add('b'); consonants.add('c');
auto intersection = vowels & consonants; // 교집합
auto union_set = vowels | consonants; // 합집합
```### Pattern 3: Bit field compression```cpp
class CompactData {
std::bitset<32> flags_;
public:
// 0-7: 타입 (8비트)
void setType(uint8_t type) {
for (int i = 0; i < 8; ++i) {
flags_[i] = (type >> i) & 1;
}
}
uint8_t getType() const {
uint8_t type = 0;
for (int i = 0; i < 8; ++i) {
if (flags_[i]) {
type |= (1 << i);
}
}
return type;
}
// 8-15: 상태 플래그
void setFlag(int index, bool value) {
flags_[8 + index] = value;
}
bool getFlag(int index) const {
return flags_[8 + index];
}
};
```## FAQ
### Q1: What is bitset?
A: An STL container representing a fixed-size set of bits. Data can be efficiently stored and manipulated bit by bit.
### Q2: How is the size of the bitset determined?
A: Fixed as a template argument at compile time. The size cannot be changed at runtime.```cpp
std::bitset<8> bits; // 8비트 고정
```### Q3: What bit operations are supported?
A: Supports AND(`&`), OR(`|`), XOR(`^`), NOT(`~`), left shift (`<<`), and right shift (`>>`).```cpp
std::bitset<8> b1{"11110000"};
std::bitset<8> b2{"10101010"};
auto result = b1 & b2; // AND
```### Q4: Can I convert it to integer or string?
A: It is possible. Use `to_ullong()`, `to_ullong()`, and `to_string()`.```cpp
std::bitset<8> bits{"10101010"};
unsigned long ul = bits.to_ulong();
std::string str = bits.to_string();
```### Q5: What is the difference from vector<bool>?
A:
- bitset: fixed size, determined at compile time.
- vector<bool>: Dynamic size, changeable at runtime.```cpp
std::bitset<8> bits; // 고정
std::vector<bool> vec(8); // 동적
vec.resize(16); // OK
```### Q6: What is the memory size of bitset?
A: Number of bits divided by 8 (in bytes). For example, `bitset<8>` is 1 byte, `bitset<32>` is 4 bytes.
### Q7: What is the bit index direction?
A: Index 0 is the right bit.```cpp
std::bitset<8> bits{"10101010"};
// 76543210 (인덱스)
bits[0]; // 0 (오른쪽)
bits[7]; // 1 (왼쪽)
```### Q8: What are bitset learning resources?
A:
- "C++ Primer" by Lippman, Lajoie, Moo
- "Effective STL" by Scott Meyers
- [cppreference.com - std::bitset](https://en.cppreference.com/w/cpp/utility/bitset)
Related article: [Bit Manipulation](/blog/cpp-bit-manipulation/), Bit Fields.
One-line summary: `std::bitset` is a fixed-size bit set that is memory efficient and allows for intuitive bitwise operations.
---
## Good article to read together (internal link)
Here's another article related to this topic.
- [C++ Algorithm Set | “Set Algorithm” Guide](/blog/cpp-algorithm-set/)
- [C++ Custom Allocator | “Custom Allocator” Guide](/blog/cpp-custom-allocator/)
- [C++ function object | "Functor" complete guide](/blog/cpp-function-objects/)
## Practical tips
These are tips that can be applied right away in practice.
### Debugging tips
- If you run into a problem, check the compiler warnings first.
- Reproduce the problem with a simple test case
### Performance Tips
- Don't optimize without profiling
- Set measurable indicators first
### Code review tips
- Check in advance for areas that are frequently pointed out in code reviews.
- Follow your team's coding conventions
---
## Practical checklist
This is what you need to check when applying this concept in practice.
### Before writing code
- [ ] Is this technique the best way to solve the current problem?
- [ ] Can team members understand and maintain this code?
- [ ] Does it meet the performance requirements?
### Writing code
- [ ] Have you resolved all compiler warnings?
- [ ] Have you considered edge cases?
- [ ] Is error handling appropriate?
### When reviewing code
- [ ] Is the intent of the code clear?
- [ ] Are there enough test cases?
- [ ] Is it documented?
Use this checklist to reduce mistakes and improve code quality.
---
## Keywords covered in this article (related search terms)
This article will be helpful if you search for C++, bitset, bit, flags, STL, etc.
---
## Related articles
- [C++ Algorithm Copy | ](/blog/cpp-algorithm-copy/)
- [C++ Algorithm Count | ](/blog/cpp-algorithm-count/)
- [C++ Algorithm Generate | ](/blog/cpp-algorithm-generate/)
- [C++ Algorithm | ](/blog/cpp-algorithm-guide/)
- [C++ Algorithm Heap | ](/blog/cpp-algorithm-heap/)