[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)를 이용하는 방법이 있습니다.

공용체를 이용한 구현은 다음 포스트에서 볼 수 있습니다 >[C]공용체(Union)





© 2021.02. by kirim

Powered by kkrim