본문 바로가기
c언어

c언어 비트 필드 구조체에 대하여 알아보기

by 개발자 L 2023. 2. 22.
반응형

c언어 비트 필드 구조체에 대하여 알아보기

네 안녕하세요, 이번 포스팅에서는 비트 필드구조체에 대하여 알아보도록 하겠습니다.

비트 필드 구조체는 구조체의 한 종류인데,

일반적인 구조체와는 좀 다른 특징을 지니고 있습니다.

그럼 어떤 특징이 있는지 한 번 보도록 하겠습니다.

 

1. 비트 필드 구조체란?

비트 필드 구조체는 쉽게 말하면 구조체의 멤버들일 비트 단위로 쪼개져 있는 구조체입니다.

그렇기 때문에 비트들을 멤버로 가지며,

비트를 원하는 만큼 할당할 수 있기 때문에 메모리 효율이 그만큼 올라갑니다.

간단한 예시로 상품 정보를 저장하는 비트 필드 구조체를 작성해 보도록 하겠습니다.

struct product
{
    unsigned style : 3;
    unsigned size : 2;
    unsigned color : 1;
};

이렇게 스타일, 사이즈, 색상에 관한 비트 필드를 정의했습니다.

여기서 숫자들은 할당이 된 비트 수를 의미하는데,

이 비트를 표현할 때는 반드시 숫자 앞에 콜론(:)이 있어줘야 하며,

의미는 제일 위에 스타일을 예로 들어 설명을 드리자면,

unsigned style이라는 문장이 3개 존재한다는 뜻이 됩니다.

그리고 이러한 자료형을 쓸 때 unsigned 자료형을 가지고 표현을 많이 하는데,

unsigned 자료형의 경우 c/c++에서는 32비트로 표현이 되므로, 0에서 32까지의 숫자를 사용할 수 있습니다.

그리고 각각은 2진법을 쓰기 때문에, 할당이 된 숫자는 지수, 다시 말하면 승수입니다.

그래서 2의 n제곱으로 읽으시면 됩니다.

따라서 1이면 0과 1 두 개를 쓸 수 있고,

2라면 0에서 3까지, 4개를 쓸 수 있으며,

3이라면 0에서 7까지 8개를 쓸 수 있습니다.

제가 방금 작성한 코드를 이용해서 간단한 코드를 작성해 보도록 하겠습니다.

#include <stdio.h>

struct product
{
    unsigned style : 3;
    unsigned size : 2;
    unsigned color : 1;
};

int main()
{
    struct product p1;

    p1.style = 5;
    p1.size = 3;
    p1.color = 1;

    printf("style = %d, size = %d, color = %d\n", p1.style, p1.size, p1.color);
    printf("sizeof(p1) = %d\n", sizeof(p1));
    printf("p1 = %x\n", p1);

    return 0;
}

이렇게 작성을 해봤습니다.

그럼 결과를 보여드리도록 하겠습니다.

style = 5, size = 3, color = 1
sizeof(p1) = 4
p1 = 4000bd

여기서 보면 알 수 있는 사실은,

색 빼고는 다 다른 수가 들어간 것을 알 수 있습니다.

하지만 비트 필드를 사용하게 되면 컴파일러가 알아서 비트 이동 연산을 수행하기 때문에 값 오류가 없이 잘 나오고,

sizeof() 함수를 쓰게 되면 현재 할당된 비트 수의 값이 정수형으로 반환이 되기 때문에 4가 나오게 되며,

제일 마지막으로 16진수를 출력했을 때는 제일 마지막 비트를 제외하고 다 쓰레기 값이 들어간 것을 볼 수 있습니다.

반응형

 

2. 비트 필드를 사용할 때 주의할 점

비트 필드를 사용할 때는 몇 가지 주의 사항이 있는데, 같이 보도록 하겠습니다.

 

2 - 1. 이름은 없고 자리만 차지하는 비트 필드를 둘 수 있다.

이름이 없는 비트 필드를 둘 수 있습니다.

이런 식으로 말이죠.

struct product
{
    unsigned style : 3;
    unsigned size : 2;
    unsigned color : 1;
    unsigned : 2; // 이름 없는 비트 필드
};

이를 두는 이유는 해당 워드들의 경계에 비트 필드가 걸치게 되면 입출력 속도가 매우 느려져서

이런 이름 없는 필드를 두어 이다음에 실행이 되는 멤버가

제일 첫 워드에서 실행이 되도록, 다시 말하면 입출력을 빠르게 하기 위해 씁니다.

 

2 - 2. 크기가 0인 비트 필드를 둘 수 있다.

크기가 0인 비트 필드 역시 둘 수 있습니다.

struct product
{
    unsigned style : 3;
    unsigned : 0; // 크기가 0인 비트 필드
    unsigned size : 2;
    unsigned color : 1;
};

크기가 0인 비트 필드의 의미는 이 워드가 실행되면 이전까지 사용하지 않은 모든 비트들이 버려집니다.

위 코드로 예를 들면 style에는 3이 할당이 되고, 남은 비트들은 0인 비트 필드를 만나면서 버려지며,

그다음에 나오는 워드에서 size와 color는 할당이 됩니다.

이 역시 메모리 효율을 위해서 하곤 합니다.

 

2 - 3. 비트 필드 크기를 지정할 때, 워드의 크기를 넘어설 수 없다.

한 워드는 unsigned를 기준으로 한다 그랬죠?
그래서 32비트를 넘어설 수 없습니다.

아래의 코드는 에러가 납니다.

struct product
{
    unsigned style : 3;
    unsigned option : 34; // 크기가 32비트를 초과하므로 에러가 남
    unsigned size : 2;
    unsigned color : 1;
};

 

2 - 4. 비트 필드 내에 일반 멤버도 넣을 수 있다.

비트 필드 내에는 일반 멤버와 비트 필드 멤버를 같이 사용할 수 있습니다.

이렇게 말이죠.

struct product
{
    int number; // 일반 멤버도 같이 쓸 수 있음
    unsigned style : 3;
    unsigned size : 2;
    unsigned color : 1;
};

 

3. 비트 필드의 응용 분야

보통 비트 필드는 간단한 데이터들을 입력받아 표현하는 경우,

그리고 가장 큰 이유는 메모리 공간을 아끼기 위해서이고,

특히 이러한 비트 필드는 하드웨어 제어를 할 때 정말 많이 쓰입니다.

컴퓨터에 연결이 되는 하드웨어 장치들은 기본적으로 비트 단위로 제어를 하도록 설계가 되어있기 때문에

관련 소프트웨어를 넣을 때 비트 필드를 사용해 정의를 합니다.

 

여기까지 비트 필드 구조체에 대하여 알아보았습니다.

다음 포스팅에서는 지금까지 배웠던 것들을 이용하여 여러 가지 문제들을 풀어보는 시간을 가져보도록 하겠습니다.

긴 글 읽어주신 독자분들께 진심으로 감사합니다~

반응형

댓글