[2026] C++ bitset | Bit Set Guide
이 글의 핵심
This is a bitset guide that summarizes the basics of bit operations, bitset vs vector<bool>, masking, permutation, and combination patterns, and performance.
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를 사용한 구현 예제입니다. 필요한 모듈을 import하고. 코드를 직접 실행해보면서 동작을 확인해보세요.
#include <bitset>
// 실행 예제
std::bitset<8> bits; // 8비트
bits.set(0); // 0번 비트 1
bits.set(3); // 3번 비트 1
bits.reset(0); // 0번 비트 0
Why do you need it?:
- 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를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
```cpp
std::bitset<8> bits{"10101010"};
// 76543210 (인덱스)
std::cout << bits[0] << '\n'; // 0 (오른쪽)
std::cout << bits[7] << '\n'; // 1 (왼쪽)
// 주의: 문자열과 인덱스 방향이 반대!
```## Default use
아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
```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를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
```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를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
```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를 사용한 구현 예제입니다. 필요한 모듈을 import하고. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
```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를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
```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를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
```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를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
```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를 사용한 구현 예제입니다. 필요한 모듈을 import하고, 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
```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를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
```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를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
```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를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
```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 코드 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
```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/)