bool자료형의 경우 1byte의 크기를 가지지만, 사실 true, false 2개의 값만을 가지기에 1bit만이 필요함bool변수를 한 번에 모아서 사용하도록 하기 위해 bit 변수를 사용#include <bitset> // for std::bitset
std::bitset<8> bits {}; // 8 bit짜리
bits = 0b0000'0101; // 초기화
0b0000'0101의 경우 0, 2번째에 해당하는 bool 값이 1로 설정되어 있다uint8_t, uint16_t, uint32_t 를 사용#include <cstdint> // std::uintN_t
constexpr std::uint8_t bits8 { 0b0100'1011 };
constexpr std::uint16_t bits16 { 0x5B9D };
constexpr std::uint32_t bits32 { 0x001F'5B9D };
std::cout << bits8 << ',' << sizeof(bits8); // K,1
std::cout << bits32 << ',' << sizeof(bits32); // 2055069,4
8, 16, 32 bit의 메모리만 사용하여 메모리 효율이 아주 좋다
그러나 bit로 데이터를 해석하지 않음
uint8_t : C++에선 uint8_t가 실제로는 unsigned char로 정의되어 있음. 따라서 0b0100'1011은 75로 저장되어 K를 출력uint16_t : unsigned short 또는 unsigned short int로 정의됨. 정수형으로 취급된다uint32_t : unsigned int로 정의되어 기본 정수형으로 취급됨따라서 캐스팅을 통해 원하는 자료형으로 출력하거나 사용해야 함
std::cout << static_cast<int>(bits8); // 정수로 변환. 75
std::cout << std::bitset<8>(bits8); // bit로 변환. 01001011
#include <bitset> // std::bitset
constexpr std::bitset<8> bitset8 { 0b1001'0001 }; // 145
constexpr std::bitset<8> bitset8 { 145 }; // 위와 동일
constexpr std::bitset<16> bitset16 { 0x4561 };
std::cout << bitset8; // 10010001
std::cout << sizeof(bitset8); // 4
// 이진수 문자열로 생성
std::bitset<8> bits(std::string("11001100")); // 이진수 문자열만 가능
// bitset → 이진수 문자열
std::string binaryStr = bits.to_string(); // "11001100"
// bitset → 정수(unsigned long)
unsigned long num = bits.to_ulong(); // 204
constexpr int isHungry { 0 };
constexpr int isSad { 1 };
constexpr int isMad { 2 };
constexpr int isHappy { 3 };
constexpr int isLaughing { 4 };
constexpr int isAsleep { 5 };
constexpr int isDead { 6 };
constexpr int isCrying { 7 };
std::bitset<8> me{ 0b0000'0000 };
me.set(isHappy); // set bit position 3 to 1 (0000 1000)
me.set(isHungry); // set bit position 0 to 1 (0000 1001)
me.set(isCrying); // set bit position 7 to 1 (1000 1001)
me.flip(isLaughing); // flip bit 4 (1001 1001)
me.reset(isLaughing); // set bit 4 back to 0 (1000 1001)
std::cout << me; // 1000 1001 반환
std::cout << "I am happy: " << me.test(isHappy) << '\n'; // 1반환
std::cout << "I am laughing: " << me.test(isLaughing) << '\n'; // 0반환
std::bitset<8> bits{ 0b0000'1101 };
std::cout << bits.size(); // 8
std::cout << bits.count(); // 3
std::cout << std::boolalpha;
std::cout << bits.all(); // false
std::cout << bits.any(); // true
std::cout << bits.none(); // false


bitset은 bit data를 관리하기 위한 클래스 타입으로, 비트 연산자가 bitset끼리만 동작하도록 연산자 오버로딩이 되어 있음 constexpr std::bitset<8> bitset_bits{ 0b0010'0100 };
constexpr std::uint8_t uint_bits{0b1001'0001};
std::cout << bitset_bits & uint_bits; // error : bitset끼리만 연산해야함
uint8_t ub = 0b1010'1010;
std::bitset<8> bs("11110000");
// bitset을 unsigned long으로 변환 후 계산
uint8_t u_bs = static_cast<uint8_t>(bs.to_ulong());
auto result = ub & u_bs; // result: 0b10100000 (int)
// uint를 bitset으로 변환 후 계산
std::bitset<8> bs_ub(ub);
auto result_bs = bs_ub & bs; // result: 0b10100000 (bitset)
int보다 작은 uint8_t, uint16_t, uint32_t들은 비트 연산시에 int로 승격(변환)되어 연산됨bitset은 이러한 type 승격 없이 연산이 이루어짐#include <cstdint>
#include <bitset>
// uint8_t에 비트 연산시키면 결과는 int 타입
uint8_t v = 0b00001111;
auto res = ~v; // res는 int 타입, 0xFFFFFFF0
// bitset로 비트 연산하면 결과는 bitset<8> 타입 그대로
std::bitset<8> b1("00001111");
auto res2 = ~b1; // res2 역시 bitset<8> 타입, 11110000
std::uint8_t c { 0b00001111 }; // int보다 작으므로 int로 변환되어 연산
std::cout << std::bitset<32>(~c); // 11111111111111111111111111110000
std::cout << std::bitset<32>(c << 6) // 00000000000000000000001111000000
std::uint8_t cneg { ~c }; // error
c = ~c; // possible warning
0b00001111이 int형인 0000'0000'0000'0000'0000'0000'0000'1111으로 변환되어 비트 연산 진행됨~의 경우 앞에 28개의 1이 생성<<의 경우에도 0b1100'0000에서 32bit로의 변환을 기대했으나 애초에 int로 계산되므로 그렇지 않은 결과가 나옴cneg의 경우 리스트 초기화를 하였으므로, int를 uint8_t인 다른 자료형으로 초기화하려니 에러발생c = ~c;은 경고만 발생 (narrowing : int -> uint8_t)static_cast를 통해 계산 값을 원래 자료형으로 돌리고 후에 다시 원하는대로 변환 std::uint8_t c { 0b00001111 };
// 00000000000000000000000011110000
std::cout << std::bitset<32>(static_cast<std::uint8_t>(~c));
// 00000000000000000000000011000000
std::cout << std::bitset<32>(static_cast<std::uint8_t>(c << 6));
std::uint8_t cneg { static_cast<std::uint8_t>(~c) };
c = static_cast<std::uint8_t>(~c);
bitset을 이용한 계산 성능이 훨씬 뛰어나므로, 대부분의 bit data에는 bitset 사용하는 것이 더 좋다uintN_t는 메모리 효율성이 중요하고, 계산이 거의 없는 단순 데이터 저장용으로 좋다Bit Mask를 통해 원하는 bit만 수정
// 여러 형태로 bit mask 설정 가능(8 bitset 기준)
constexpr std::uint8_t mask0{ 0b0000'0001 };
constexpr std::uint8_t mask1{ 0b0000'0010 };
constexpr std::uint8_t mask2{ 0b0000'0100 };
constexpr std::uint8_t mask3{ 1 << 3 }; // 0000 1000
constexpr std::uint8_t mask4{ 1 << 4 }; // 0001 0000
constexpr std::uint8_t mask5{ 0x20 }; // hex for 0010 0000
constexpr std::uint8_t mask6{ 0x40 }; // hex for 0100 0000
constexpr std::uint8_t mask7{ 0b1000'0000 };
std::uint8_t myBits{ 0b0000'0101 };
&|~, & 사용^ 사용std::uint8_t myBits{ 0b0000'0101 };
// &로 bit 값 확인
std::cout << (static_cast<bool>(flags & mask0); // 1
std::cout << (static_cast<bool>(flags & mask1); // 0
// |로 bit turn on
flags |= mask1; // 0000'0111
flags |= (mask4 | mask5); // 0011'0111 (동시에)
// bit 값 초기화
flags &= ~mask2; // 0011'0011
flags &= ~(mask1 | mask5); // 0001'0001 (동시에)
// bit flip
flags ^= mask2; // 0001'0101
flags ^= (mask4 | mask5); // 0010'0101 (동시에)
bitset의 함수 이용하는 것도 가능하나, Bit mask를 사용하면 한 번에 여러 bit를 관리할 수 있다bitset을 이용한 예시 constexpr std::bitset<4> isHungry { 0b0001 };
constexpr std::bitset<4> isSad { 1 << 1 };
constexpr std::bitset<4> isMad { 4 };
constexpr std::bitset<4> isHappy { "1000" };
std::bitset<4> me{};
me |= (isHungry | isHappy); // I am hungry and happy
me &= ~isHungry; // I am no longer hungry
// bitset이므로 any()로 state 확인
std::cout << std::boolalpha;
std::cout << "I am happy? " << (me & isHappy).any();
std::cout << "I am sad? " << (me & isSad).any();
std::cout << "I am hungry or sad? " << (me & (isHungry | isSad)).any();
uint_t를 이용한 예시 constexpr std::uint8_t isHungry { 0b0001 };
constexpr std::uint8_t isSad { 1 << 1 };
constexpr std::uint8_t isMad { 0b0100 };
constexpr std::uint8_t isHappy { 0b1000 };
std::uint8_t me{};
me |= (isHungry | isHappy); // I am hungry and happy
me &= ~isHungry; // I am no longer hungry
// uint이므로 직접 state 확인
std::cout << std::boolalpha;
std::cout << "I am happy? " << static_cast<bool>(me & isHappy);
std::cout << "I am laughing? " << static_cast<bool>(me & isLaughing);
void someFunction(bool option1, bool option2, bool option3, bool option4,
bool option5, bool option6, bool option7, bool option8, bool option9,
bool option10, bool option11, bool option12, bool option13, bool option14,
bool option15, bool option16, bool option17, bool option18, bool option19,
bool option20, bool option21, bool option22, bool option23, bool option24,
bool option25, bool option26, bool option27, bool option28, bool option29,
bool option30, bool option31, bool option32);
bool형 매개인자를 일일이 다 받기보단, bit형으로 한 번에 관리void someFunction(std::bitset<32> options);
someFunction(option10 | option32);
#define GL_DEPTH_BUFFER_BIT 0x00000100
#define GL_COLOR_BUFFER_BIT 0x00004000
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // OpenGL
// Bit mask
constexpr std::uint32_t redBits{ 0xFF000000 };
constexpr std::uint32_t greenBits{ 0x00FF0000 };
constexpr std::uint32_t blueBits{ 0x0000FF00 };
constexpr std::uint32_t alphaBits{ 0x000000FF };
std::cout << "Enter a 32-bit RGBA color value in hexadecimal (FF7F3300): ";
std::uint32_t pixel{};
std::cin >> std::hex >> pixel; // hex 값으로 받음
// Bit Mask와 비트 연산자를 통해 각 RGBA의 값 추출
std::uint8_t red{ static_cast<std::uint8_t>((pixel & redBits) >> 24) };
std::uint8_t green{ static_cast<std::uint8_t>((pixel & greenBits) >> 16) };
std::uint8_t blue{ static_cast<std::uint8_t>((pixel & blueBits) >> 8) };
std::uint8_t alpha{ static_cast<std::uint8_t>(pixel & alphaBits) };
std::cout << "Your color contains:\n";
std::cout << std::hex; // hex 값으로 출력
// uint8_t는 출력시 문자로 출력하므로, int로 변환 후 출력
std::cout << static_cast<int>(red) << " red\n";
std::cout << static_cast<int>(green) << " green\n";
std::cout << static_cast<int>(blue) << " blue\n";
std::cout << static_cast<int>(alpha) << " alpha\n";
Enter a 32-bit RGBA color value in hexadecimal (e.g. FF7F3300): FF7F3300
Your color contains:
ff red
7f green
33 blue
0 alpha