C++프로그래밍/C 와 C++ 기초실습

비트연산과 비트플래그

season97 2024. 9. 16. 10:56

※ C / C++을 이미 알고 있으나 개인적인 공부 및 복습을 위해 포스팅 하는 글이므로

C++에 대한 구체적인 정보를 담고 있지 않습니다.

▶ 비트연산

- 언제 필요한가? 
비트 단위의 조작이 필요할때. 대표적으로 비트플래그

~  :  (bitwise not)

ㆍ 단일 숫자의 모든 비트를 대상으로 0은 1, 1은 0으로 뒤바뀜

ㆍ 즉 모든 숫자를 반대로 (1 0)

&  :  (bitwise and)

ㆍ 두 비트가 둘다 1이면 1, 아니면 0 

|  :  (bitwise or)

ㆍ 비트 둘중 하나라도 1이면 1 아니면 0

 

^  :  (bitwise xor) 
※ 레지스터 공부할때 암호학에서 좋다한놈이다!
ㆍ 두 숫자의 모든 비트쌍을 대상으로 xor을 한다.

ㆍ 두 숫자가 같으면 0, 다르면 1

xor예시


<< : 비트를 좌측으로 이동

ㆍ 비트열을 N만큼 왼쪽으로 이동한다

ㆍ 왼쪽의 넘치는 비트는 버린다 (범위 밖의 비트는 어딘가 저장되는 것이 아닌 분실이 된다)

ㆍ 새로 생성되는 N개의 비트는 0으로 채워진다.

ㆍ *2를 할 때 자주 보이는 패턴

>> : 비트를 우측으로 이동

ㆍ 비트열을 N만큼 오른쪽으로 이동

ㆍ 오른쪽의 넘치는 N개의 비트는 버린다.

ㆍ 왼쪽 생성되는 N개의 비트는 어떻게 할것인가??

 

※ bit flag를 할 땐 unsigned로 선언해야 좋은 이유 

 

★우측 시프트연산을 하면 부호 비트가 존재할 경우 부호 비트를 따라감(부호있는 정수라면 이부분을 주의하자)
ㄴ> 이게 무슨소리? C++의 경우엔 unsigned가 아니라면 부호가 있다는소리
★ 아니면 대부분의 경우엔 0 
★ 따라서 비트단위를 무언가를 만질때는 unsigned로 만드는게 정신 건강에 좋다.

 

▶ bit flag 실습

#include <iostream>
using namespace std;

unsigned char flag;
int main()
{

	/*
	실습
	0b0000 [무적][변이][스턴][공중부양] 
	-> 4개의 상태이상은 동시에 걸릴 수도 있다. 
	-> 각각의 숫자가 상태이상의 on/off다
	*/
	
	//무적 상태로 만든다
	flag = (1 << 3); //1이라는 숫자를 왼쪽으로 3칸 쉬프트하겠다.
	
	// 변이 상태를 추가한다 (무적 + 변이)
	flag |= (1 << 2);

	// 무적인지 확인하고 싶다(다른 상태는 관심 없음)
	// bitmask
	bool invincible = (flag & (1 << 3)) != 0;

	// 무적이거나 스턴이거나? 
	bool mask = (1 << 3) | (1 << 1);
	bool stunOrInvincible = ((flag & 0b1010) != 0);
	//0b1010을 넣거나 mask를 넣거나.

	cout << flag << endl;
}

ㆍ  flag를 이용한 이것저것 실습을 해줬다.

ㆍ 0b1010 이런식으로 직접 비트를 넣어줘도 되고 10진수로 입력해줘도 문제 없다.

     ㄴ> 하지만 숫자가 커지면 커질수록 쉬프트연산을 하는게 더 편할 것이다.

 

※성능적으론 차이가 없을까?

어셈블리 테스트

※ 어셈블리로 확인해 본 결과 1<<3 으로 flag에 넣어 준 값이 어처피 8로 들어가고 있다.

따라서 가독성 좋은걸 사용하면 되겠다.