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. 비트 필드의 응용 분야
보통 비트 필드는 간단한 데이터들을 입력받아 표현하는 경우,
그리고 가장 큰 이유는 메모리 공간을 아끼기 위해서이고,
특히 이러한 비트 필드는 하드웨어 제어를 할 때 정말 많이 쓰입니다.
컴퓨터에 연결이 되는 하드웨어 장치들은 기본적으로 비트 단위로 제어를 하도록 설계가 되어있기 때문에
관련 소프트웨어를 넣을 때 비트 필드를 사용해 정의를 합니다.
여기까지 비트 필드 구조체에 대하여 알아보았습니다.
다음 포스팅에서는 지금까지 배웠던 것들을 이용하여 여러 가지 문제들을 풀어보는 시간을 가져보도록 하겠습니다.
긴 글 읽어주신 독자분들께 진심으로 감사합니다~
'c언어' 카테고리의 다른 글
c언어 동적 할당 메모리에 대하여 알아보기 (0) | 2023.02.22 |
---|---|
c언어 여러가지 전처리기와 매크로, 다중 소스 파일을 이용하여 여러 가지 문제 풀기(ASSERT 매크로 작성하기, 비트 매크로 작성하기, 여러가지 버전 정의하기(디럭스 버전과 스탠다드 버전 정.. (0) | 2023.02.22 |
c언어 다중 소스 파일에 대하여 알아보기 (2) | 2023.02.22 |
c언어 #if, #else, #elif, #endif에 대하여 알아보기 (0) | 2023.02.21 |
c언어 #ifdef와 #endif, #ifndef, #undef에 대하여 알아보기 (0) | 2023.02.21 |
댓글