[C]비트플래그
이번 포스트는 비트플래그에 관한 내용입니다.
1️⃣ 비트 연산자
연산자 | 설명 | 예시 (A = 1100 1010, B = 0111 0010 |
---|---|---|
& | 논리 곱(AND) | A & B -> 0100 0010 |
| | 논리 합(OR) | A | B -> 1111 1010 |
^ | 다르면 1(XOR) | A ^ B -> 1011 1000 |
~ | 보수(NOT) | ~A -> 0011 0101 |
<< | 왼쪽 1비트 이동 | A<<2 -> 0010 1000 |
>> | 오른쪽 1비트 이동 | A>>2 -> 0011 0010 |
2️⃣ 비트 플래그(구조체)
(1) 비트 플래그 구조체
- 비트플래그를 만들면
unsigned char(1바이트)
의 크기를 1비트단위로 접근하여 사용이 가능합니다.(다른 자료형도 1비트단위로 접근이 가능) - 1비트로는 0 혹은 1로 참과 거짓을 나타내는데 사용될 수 있습니다. 사실 이와 같은 기능을 bool자료형이하고 있습니다. 하지만 bool자료형은 C99부터 지원(<stdbool.h>헤더에 선언)하는 자료형이기 때문에 그 이전버전에는 지원하지 않습니다.
- 또한 참과 거짓을 표현하는데에는 1비트의 크기만 필요하지만 bool형자료형은 1바이트의 메모리를 차지합니다.
- 그러기 때문에 구조체 형식의 비트 플래그를 직접구현해서 사용한다면 C99이전버전에서 사용이 가능하고, 보다 적은 메모리를 가지고 bool자료형과 같이 이용이 가능할 것입니다.
< 비트 플래그 구현(구조체) >
typedef struct
{
unsigned char b1 : 1;
unsigned char b2 : 1;
unsigned char b3 : 1;
unsigned char b4 : 1;
unsigned char b5 : 1;
unsigned char b6 : 1;
unsigned char b7 : 1;
unsigned char b8 : 1;
} bitflag_t;
(2) 비트 플래그 구조체의 한계
- 요소 하나씩의 비트는 비교가 가능합니다.
- 하지만 전체 비트를 한번에 비교 못합니다.
< 비트 플래그 구조체의 비교 >
int main(void)
{
bitflag_t flags = { 0, };
int bool_b1 = (flags.b1 == 1); // OK
int compare_two = (flags.b2 == flags.b6); // Ok
int compare_all_1 = (flags == 0xFF); // 컴파일 오류
int compare_all_2 = (flags == 0); // 컴파일 오류
}
(3) 편법으로 비트 플래그 구조체 비교(포인터 이용)
- 포인터의 기능은 막강하기 때문에 다음과 같이
char*
포인터로 구조체의 주소를 받아오면 구조체 비트 전체를 한번에 비교할 수 있습니다.
< 편법으로 전체비트 비교 >
int main(void)
{
bitflag_t flags = { 0, };
char *address_flags;
address_flags = (char *)&flags; // 강제로 주소를 읽어옴
int compare_all_1 = (address_flags == 0xFF); // OK
int compare_all_2 = (address_flags == 0); // OK
}
하지만 실수할 가능성이 크고 이런식으로 포인터를 사용하는 것은 그렇게 좋은 방법이라고 생각하지 않습니다.
그 대신 공용체(union)를 이용하는 방법이 있습니다.