[C++] 비트 논리 연산자의 사용


두 값을 2진수로 변환한 뒤 비트 단위로 연산하여 값을 반환한다.

그리고 비트 논리 연산자는 아래와 같이 4가지가 존재하는데 연산 방법은 다음과 같다.

기호
이름
참의 조건
&AND두 비트가 모두 1이어야 참
|OR두 비트 중 하나라도 1이라면 참
~NOT비트를 반전시킨다.
^XOR두 비트가 서로 다르면 참


연산 예시를 들어보자.


379와 296을 연산하기 위해서 우선 두 수를 2진수로 변환한다.

  • 379 : 101111011 (2진수)
  • 296 : 100101000 (2진수)

그리고 각 비트마다 연산을 진행해보자.

and 연산을 실시하면?


두 비트가 모두 1이어야 참이므로 왼쪽부터 연산을 진행하면 결과값은 아래와 같이 반환된다.

100101000

이 값을 10진수로 변환시키면 296이다.

따라서, 반환값은 296이다.

or 연산을 실시하면?


두 비트 중 하나라도 1이어야 참이므로 왼쪽부터 연산을 진행하면 결과값은 아래와 같이 반환된다.

101111011

이 값을 10진수로 변환시키면 379이다.

따라서, 반환값은 379이다.

not 연산을 실시하면?


비트 값을 반전시킨다. 379에 not 연산을 실시하면 아래와 같이 나타난다

010000100

이 값을 10진수로 변환시키면 132이다.

따라서, 반환값은 132이다.

xor 연산을 실시하면?


두 비트 값이 달라야 참이므로 왼쪽부터 연산을 실시하면 아래와 같이 나타난다.

001010011

이 값을 10진수로 변환시키면 83이다.

논리 비트 연산은 어디에 쓰일까?


2진수로 변환한 뒤 계산하기 때문에 일반적인 연산에 비해서 속도가 훨씬 빠르다.

그럼 C++에서 이런 비트연산은 어디에 쓰이는 것일까?

게임에서의 논리 비트 사용 (버프)


대표적으로 게임에서 상태, 버프 등을 표시할 때 사용할 수 있다. 각 비트 자리를 버프의 상태라고하고, 0이 버프가 꺼진 상태, 1이 버프가 켜진 상태라고 해보자.

즉, 버프가 켜졌는지 여부를 1111, 1010, 등 으로 표현을 하고, 0000과 논리 비교를 하면 어떤 버프가 켜졌고 어떤 버프가 꺼졌는지 정수로 표현이 가능하다.

ex) 버프가 5개일 경우

00000 (버프가 모두 꺼짐)

10110 (1, 3, 4 번 버프가 켜짐.)
const int reset_buf_all = 0;
const int attack = 0x1; // (00001)
const int armor = 0x2; // (00010)
const int for_hp = 0x4; // (00100)
const int for_mp = 0x8; // (01000)
const int critical = 0x10; // (10000)

int buf = 0; // 00000

이렇게 16진수를 이용해서 각 버프의 상태를 상수로 부여할 수 있다.


이때, 신기하게도(or) 연산을 사용해서 버프를 켤 수 있다.
	buf = buf | attack; // 공격 버프가 켜짐. (00001)

	buf = buf | armor; // 방어 버프가 켜짐 (00010)

	// 현재 공격, 방어 버프가 켜진 상태 (buf = 00011)

	buf = reset_buf_all; // 버프 전체 초기화 (buf = 00000)

	buf = buf | (attack + armor); // 공격 및 방어 버프가 켜짐(00011)

	buf = buf | critical; // 크리티컬 버프가 켜짐 (10011)


그리고 and 연산을 사용해서 버프의 상태를 확인할 수 있다.

	std::cout << "Attack : " << (buf & attack) << std::endl;
    // 1 (0이 아님. 버프가 켜진 상태)

	std::cout << "armor : " << (buf & armor) << std::endl;
    // 2 (0이 아님. 버프가 켜진 상태)

	std::cout << "HP : " << (buf & for_hp) << std::endl;
    // 0 (0임. 버프가 꺼진 상태)

	std::cout << "MP : " << (buf & for_mp) << std::endl;
    // 0 (0임. 버프가 꺼진 상태)

	std::cout << "critical : " << (buf & critical) << std::endl;
    // 16(0이 아님. 버프가 켜진 상태)

프로그래밍 언어에선 값이 0이면 거짓, 0이 아니라면 참임을 이용해서 참과 거짓을 판별할 수 있다. 이를 이용해서 and연산을 통해서 버프의 상태를 확인할 수 있다.

그리고 xor 연산을 통해서 버프를 켜거나 끌 수 있다.

	buf = buf ^ armor;

	std::cout << "armor : " << (buf & armor) << std::endl;
    // 0 (0임. 아머 버프가 꺼졌음.)
	std::cout << "현재 버프 상태 : " << buf << std::endl;
    // 17 (10001)

	// 단, 여기서 한번 더 xor 연산을 해버릴 경우
	buf = buf ^ armor;
	std::cout << "현재 버프 상태 : " << buf << std::endl;
    // 19 (10011) 버프가 다시 켜진다.

다시 정리하면 이렇게 된다.

  • & 연산을 통해서 버프의 상태를 확인할 수 있다.
  • | 연산을 통해서 버프를 킬 수 있다.
  • ^ 연산을 통해서 버프를 켜고 끌 수 있다.

© 2022.07. by Wookey_Kim

Powered by Hydejack v7.5.2