지난 시간에는 비트 시프트 연산과 비트 논리 연산자, 그리고 #define 매크로의 기초 개념을 다루었다.
이번 시간에는 비트 연산자가 실무 및 게임 프로그래밍에서 실제로 어떻게 활용되는지 핵심적인 사용처인 상태 플래그(State Flag) 관리에 대해 알아본다.
1. 비트 자리를 이용한 상태 표현
32비트 정수형 변수(int) 하나는 총 32개의 0 또는 1(Bit)을 가질 수 있다. 이를 이용하면 변수 하나로 최대 32가지의 서로 다른 상태를 동시에 관리할 수 있다.
-
비트 마스킹의 원리
-
각 비트 자리에 고유한 의미(예: 배고픔, 목마름, 중독 등)를 부여한다.
-
해당 비트가
1이면 상태 활성화(ON),0이면 비활성화(OFF)를 나타낸다. -
각 상태의 값은 2의 거듭제곱() 형태를 띤다.
-
#define HUNGRY 0x001 // 1 (2^0)
#define THIRSTY 0x002 // 2 (2^1)
#define POISON 0x004 // 4 (2^2)
#define SLEEP 0x008 // 8 (2^3)
💡 16진수(0x) 표기법 활용
상태 값을 정의할 때는 10진수보다 16진수(
0x) 를 주로 사용한다. 16진수는 비트 4개 단위로 깔끔하게 떨어지기 때문에 각 비트의 위치를 직관적으로 파악하고 관리하기 쉽다.
2. 비트 연산자 필수 3대 패턴
상태 플래그를 관리할 때 자주 쓰이는 추가, 검사, 제거의 3가지 연산 패턴은 반드시 숙지해야 한다.
① 상태 추가: |= (비트 OR)
특정 비트 자리를 1로 만들어 상태를 온(ON)시킨다. 다른 비트 자리에는 영향을 주지 않는다.
unsigned int iStatus = 0;
// iStatus에 THIRSTY(목마름) 상태 추가
iStatus |= THIRSTY;
② 상태 검사: & (비트 AND)
특정 상태가 활성화되어 있는지 확인한다. 해당 비트 자리가 1이면 0이 아닌 참(True)의 값을 반환한다.
// iStatus에 THIRSTY(목마름) 상태가 있는지 검사
if (iStatus & THIRSTY) {
// 목마름 상태일 때 처리할 로직
}
③ 상태 제거: &= ~ (비트 AND + NOT)
지우고자 하는 상태 비트만 0으로 뒤집은 뒤(~) AND 연산을 수행하여 안전하게 상태를 제거한다.
// iStatus에서 THIRSTY(목마름) 상태 제거
iStatus &= ~THIRSTY;
⚠️ XOR(
^) 연산으로 상태를 제거하면 안 되는 이유XOR 연산은 비트가 다르면
1, 같으면0을 반환하므로 이미 해당 상태가 켜져 있을 땐 꺼지지만, 상태가 꺼져 있을 때 적용하면 오히려 상태가 켜져 버리는 문제가 발생한다. 따라서 상태 제거 시에는 안전하게&= ~패턴을 사용한다.
3. 실무 및 게임 개발에서의 활용
-
게임 캐릭터의 버프/디버프 관리
- 캐릭터가 현재 어떤 상태(비행, 무적, 독, 둔화 등)에 걸려 있는지 32비트 또는 64비트 변수 하나로 집약하여 빠르게 처리한다.
-
복잡한 설정을 하나의 인자로 전달
- 윈도우창 스타일 설정(최소화 버튼 유무, 닫기 버튼 유무, 창 크기 조절 여부 등)처럼 수많은 설정값을 하나의 변수에 묶어서 함수에 전달할 수 있다.
마무리하며
-
32비트 정수형 변수의 각 비트 자리를 개별적인 상태 값으로 활용하여 최대 32가지의 상태를 동시에 효율적으로 관리할 수 있다.
-
비트 OR 연산으로 특정 상태를 추가하고, 비트 AND와 반전 연산을 조합하여 특정 상태를 안전하게 제거하는 패턴은 게임 개발에서 빈번하게 사용된다.
-
복잡한 매개변수를 하나로 통합 전달하거나 윈도우 스타일 설정 등 여러 상태 값을 하나의 변수에 담아 효율적인 시스템 설계가 가능하다.