#include <bitset>
//2진수 bit 로 출력 시켜준다.
//unsigned int x = 0b1010; 2진수 표기법
int x = 10;
auto out = std::bitset<4>(10); // 10을 4자리 수의 2진수 비트로 출력
cout << out << endl; // 1010
// shift 연산자
<< : left shift
int x = 10;
auto out = std::bitset<8>(10);
out = out << 2; // 00001010 을 왼쪽으로 2칸씩 옮기고 빈 곳은 0으로 채운다. 결과는?
x = x << 2;
cout << out << endl; // 00101000이 나온다. 이는 00001010 에 2^2 을 곱하는 것과 마찬가지다. 곱 연산보다 빠르다.
cout << x << endl; // 40
<< : right shift
out = out >> 2; //오른쪽으로 2칸씩 밀고 빈 곳은 0으로 채운다. 이는 00101000 에 2^2 를 나누는 것과 마찬가지다. 나누기 연산보다 빠르다.
x = x >> 2; // 10
int a = 12;
int b = 10;
a = a & b;
cout << a << endl;
// a 는 무슨 값이 출력 될까?
& 는 and 연산자 로써 양쪽이 모두 1이어야 1로 바뀐다.
00001100 (12)
00001010 (10)
이를 and 연산 해 보면
00001000 으로 a = 8 이 됨을 확인 할 수 있다.
| 는 or 연산자 로써 하나라도 1이면 1로 바뀐다.
위의 식으로 해보면
00001110 로 a = 14 가 됨을 알 수 있다.
^ 는 xor 연산자 로써 둘이 다르면 1, 같으면 0 으로 바뀐다.
00000110 으로 a = 6 이 됨을 알 수 있다.
~ 는 1의 보수로써 비트를 반전 시킨다.
a 는 00001100 이었다.
이를 ~a 하면, 11110011 이 나온다.
이는 -13 을 나타낸다. ( - 붙이고 1 빼주는것과 같다.)
// 비트 플래그
게임 아이템은 상당히 많을 것이다. 아이템 개수가 64개 라면 64개의 boolean 변수로 체크 할 수 있다. 아이템의 소유 여부를 체크하는 함수가 있다면,
64개의 아이템을 체크 하는게 상당히 비 효율적이 될 수 있다.
비트에 아이템 유무 플래그를 표시하자.
unsigned int 변수 하나가 32bit를 가지고 있으니까 각 비트 자리를 아이템에 대치 시킨다.
그러면 2개의 unsigned int 변수로 64개를 표현 할 수 있다.
unsigned int items_flag = 0; // 00000000
const unsigned char item0 = 1 << 0;
const unsigned char item1 = 1 << 1;
const unsigned char item2 = 1 << 2;
const unsigned char item3 = 1 << 3;
const unsigned char item4 = 1 << 4;
const unsigned char item5 = 1 << 5;
const unsigned char item6 = 1 << 6;
const unsigned char item7 = 1 << 7;
cout << std::bitset<8>(item0) << endl; // 00000001
cout << std::bitset<8>(item1) << endl; // 00000010
cout << std::bitset<8>(item2) << endl; // 00000100
cout << std::bitset<8>(item3) << endl; // 00001000
// 이렇게 각 자리 수를 아이템으로 대치시킨다.
// OR 연산으로 아이템을 얻어보자.
// 아이템 0을 얻었다.
items_flag |= item0;
cout << std::bitset<8>(items_flag) << endl; // 00000001. flag 에 1이 채워졌다. 아이템 0번째가 소유 된 것이다.
// 아이템 1과 2를 얻는다.
items_flag |= item1 | item2;
cout << std::bitset<8>(items_flag) << endl; // 00000111. flag 에 11이 추가로 채워졌다. 1, 2번 아이템이 소유 된 것이다.
// And 연산과 보수 사용으로 아이템을 잃어보자.
// 현재 flag 는 00000111.
items_flag &= ~item1;
cout << std::bitset<8>(items_flag) << endl; // 00000101. 아이템 1번이 사라졌다.
// item1 의 보수는 11111101 이다. And 연산자는 둘 다 1이어야 1이다.
// 00000111
// 11111101 여기서 둘 다 1만 1로 바꿔주면.
// 00000101 이 나온다.
// 아이템을 소유하고 있는지 확인 해 보자.
// 그냥 & 연산자만 사용한다.
// 현재 flag 는 00000101. 1번이 없는 상태이다. 확인 해 보자.
if (items_flag & item1)
cout << "item1 번이 있어요" << endl;
else
cout << "item1 번이 없어요" << endl;
// 결과는? 없다고 잘 뜬다. 왜?
// 00000101 과 00000010 을 and 연산했다. 그 결과 00000000 으로 false 가 나온 것이다.
// 만약 flag 에 1이 채워져 있었다면 0 이 아닌 다른 수가 나왔을 테니까 true 가 나올 것이다.
// 아이템 유무를 뒤바꿔 보자.
// XOR 연산자 사용하자.
if (!(items_flag & item1) && (items_flag & item0)) { // 1번은 없고 0번이 있다면
items_flag ^= item1;
items_flag ^= item0;
}
cout << std::bitset<8>(items_flag) << endl; // 00000110. 1번은 생겼고 0번은 사라졌다.
// 비트 마스크
// RGB : Red Green Blue 각각 8bits 로 표현 할 수 있다.
// 0xFFFFFF : RGB 를 표현한다.
// 0xBAC708 로 예를 들어보자.
unsigned int color = 0xBAC708;
const unsigned red_mask = 0xFF0000;
const unsigned green_mask = 0x00FF00;
const unsigned blue_mask = 0x0000FF;
// Red 만 뽑아내 보자.
cout << std::bitset<32>(red_mask) << endl; // 00000000111111110000000000000000
cout << std::bitset<32>(color) << endl; // 00000000101110101100011100001000
unsigned char red = (color & red_mask) >> 16; // 왜 ? RGB 순서이므로 오른쪽으로 16칸 SHIFT 해줘야 RED 값이 나온다.
cout << "red 값 : " << std::bitset<8>(red) << endl; // 10111010
// Green 만 뽑아내 보자.
cout << std::bitset<32>(green_mask) << endl; // 00000000000000001111111100000000
cout << std::bitset<32>(color) << endl; // 00000000101110101100011100001000
unsigned char green = (color & green_mask) >> 8; // 왜 ? RGB 순서이므로 오른쪽으로 8칸 SHIFT 해줘야 GREEN 값이 나온다.
cout << "green 값 : " << std::bitset<8>(green) << endl; // 11000111
// Blue 만 뽑아내 보자.
cout << std::bitset<32>(blue_mask) << endl; // 00000000000000000000000011111111
cout << std::bitset<32>(color) << endl; // 00000000101110101100011100001000
unsigned char blue = (color & blue_mask);
cout << "blue 값 : " << std::bitset<8>(blue) << endl; // 00001000