C/C++을 공부하다 보면 처음엔 다소 생소하지만, 게임 프로그래밍 및 실무에서 정말 자주 쓰이는 핵심 개념 두 가지를 만나게 된다. 바로 비트 연산자와 #define 전처리기다.
자주 사용되지만 시간이 지나면 동작 방식을 잊어버리기 쉬운 개념인 만큼, 기본 원리부터 차근차근 정리해 본다.
1. 비트 시프트 연산자 (<<, >>)
비트 시프트 연산은 데이터의 비트(Bit)를 화살표가 가리키는 방향으로 한 칸씩 밀어주는 연산자다.
-
왼쪽 시프트 (
<<)-
비트를 왼쪽으로 칸 이동시킨다.
-
2진법 특성상 자릿수가 하나씩 올라가므로, 배 증가하는 효과를 가진다.
-
예:
x << 3은 ()과 동일 -
<<=대입 연산자와 결합하면 변수 값에 2의 배수를 곱해 바로 재대입할 수 있다.
-
-
오른쪽 시프트 (
>>)-
비트를 오른쪽으로 칸 이동시킨다.
-
오른쪽으로 밀리면서 범위를 벗어난 비트는 소실(삭제)된다.
-
수학적으로는 으로 나눈 몫을 구하는 원리와 같다.
-
💡 한 줄 요약
왼쪽 시프트는 을 곱한 값, 오른쪽 시프트는 으로 나눈 몫을 반환한다.
2. 비트 논리 연산자 (&, |, ^, ~)
각 자릿수별로 비트 단위 연산을 수행한다.
| 연산자 | 이름 | 설명 | 특징 |
|---|---|---|---|
& | AND (비트 곱) | 두 비트가 모두 1일 때만 1 | 특정 비트를 추출하거나 가릴 때 사용 |
| | OR (비트 합) | 두 비트 중 하나라도 1이면 1 | 특정 비트를 켜거나 추가할 때 사용 |
^ | XOR (배타적 논리합) | 두 비트의 값이 다르면 1, 같으면 0 | 비트 반전 및 상태 체크에 유용 |
~ | NOT (비트 반전) | 0은 1로, 1은 0으로 뒤집음 | 비트 전체 반전 |
3. 전처리기와 #define 매크로
비트 연산자가 실제 코드에서 어떻게 유용하게 활용되는지 이해하기 위해, 먼저 전처리기 #define을 알아본다.
전처리기(Preprocessor)란?
컴파일러가 코드를 실제 기계어로 번역하기 전, 가장 먼저 수행되는 처리 과정이다. # 기호로 시작하는 명령어가 이에 해당한다.
#define 매크로 상수의 활용
#define은 코드 내 지정한 구문(심볼)을 특정 값(숫자, 문자열 등)으로 단순 치환(Replace)해 준다.
#define HUNGRY 1
#define MAX_SIZE 100
#define을 사용하는 2가지 이유 (장점)
-
코드의 가독성 향상
- 단순 숫자
1대신HUNGRY처럼 의미가 명확한 단어를 사용하여 코드를 읽고 이해하기 쉽게 만든다.
- 단순 숫자
-
유지보수 효율 극대화
-
설정값이나 상수가 변경될 때, 코드 전체를 수정할 필요 없이
#define으로 정의된 부분만 수정하면 일괄 적용된다. -
예: 자판기의 최대 음료 수량(
MAX_SIZE)이 변경될 경우, 상단의#define설정값 하나만 변경
-
마무리하며
-
비트 시프트 연산은 의 곱셈과 나눗셈 몫을 빠르게 처리하는 수학적 원리를 갖는다.
-
비트 논리 연산자(AND, OR, XOR, NOT)의 자릿수별 처리 방식을 파악하여 상태 체크 등에 활용하자.
-
#define매크로로 의미 있는 이름을 부여하여 코드 가독성과 유지보수성을 극대화하자.