56.2 비트 필드와 공용체를 함께 사용하기

보통 사람이 코드에서 값을 지정할 때는 비트 필드를 사용하지만 CPU나 칩에 값을 설정할 때는 모든 비트를 묶어서 한꺼번에 저장합니다. 이번에는 비트 필드의 값을 한꺼번에 사용할 수 있도록 비트 필드와 공용체를 함께 사용해보겠습니다.

그림 56‑3 비트 필드와 공용체

예제를 보기 전에 지금까지 공부한 구조체와 공용체를 이용해서 그림 56‑3을 코드로 만들어보고, 예제와 비교해보세요.

struct_union_bit_field.c

#include <stdio.h>

struct Flags {
    union {    // 익명 공용체
        struct {    // 익명 구조체
            unsigned short a : 3;    // a는 3비트 크기
            unsigned short b : 2;    // b는 2비트 크기
            unsigned short c : 7;    // c는 7비트 크기
            unsigned short d : 4;    // d는 4비트 크기
        };                           // 합계 16비트
        unsigned short e;    // 2바이트(16비트)
    };
};

int main()
{
    struct Flags f1 = { 0, };    // 모든 멤버를 0으로 초기화

    f1.a = 4;     //  4: 0000 0100
    f1.b = 2;     //  2: 0000 0010
    f1.c = 80;    // 80: 0101 0000
    f1.d = 15;    // 15: 0000 1111

    printf("%u\n", f1.e);    // 64020: 1111 1010000 10 100

    return 0;
}

실행 결과

64020

먼저 비트 필드로 사용할 멤버는 익명 구조체로 감싸줍니다. 그리고 비트 필드의 값을 한꺼번에 접근할 수 있도록 unsigned short형 멤버를 선언하고 익명 공용체로 감싸줍니다. 여기서는 2바이트(16비트) 크기의 unsigned short에 정확히 맞추기 위해 비트 수를 3, 2, 7, 4로 지정했습니다.

struct Flags {
    union {    // 익명 공용체
        struct {    // 익명 구조체
            unsigned short a : 3;    // a는 3비트 크기
            unsigned short b : 2;    // b는 2비트 크기
            unsigned short c : 7;    // c는 7비트 크기
            unsigned short d : 4;    // d는 4비트 크기
        };                           // 합계 16비트
        unsigned short e;    // 2바이트(16비트)
    };
};

이제 비트 필드에 값을 할당합니다. 여기서는 각 비트 수에 맞게 값을 할당했습니다.

f1.a = 4;     //  4: 0000 0100
f1.b = 2;     //  2: 0000 0010
f1.c = 80;    // 80: 0101 0000
f1.d = 15;    // 15: 0000 1111

공용체로 감싸준 멤버 eprintf로 출력해보면 64020이 나옵니다. 즉, 비트 필드에 할당한 비트들을 차례대로 연결하면 1111 1010000 10 100이 되므로 10진수로 표현했을 때 64020이 됩니다.

printf("%u\n", f1.e);    // 64020: 1111 1010000 10 100
그림 56‑4 비트 필드와 공용체의 구성

지금까지 비트 필드에 대해 배웠는데 비트 단위로 값을 다루다보니 눈에 잘 들어오지 않았습니다. 비트 필드는 쓸 일이 많지 않으므로 이런 기능이 있다 정도로만 알아두면 됩니다.