티스토리 뷰
주의 사항!
- 이 일지는 작성하고 있는 현시점, 공부와 병행하면서 작성되고 있습니다.
- 공부 중에 떠오른 생각이나 그때그때의 개념정리 같은 내용이 포함됩니다.
- 따라서 이 일지의 내용은 제가 공부하고 이해한 대로 작성되기 때문에 실제 사실과는 다를 수 있습니다
이번 시간은 '비트 필드 구조체'에 관한 내용입니다.
구조체가 int형 멤버를 10개 갖는다면 구조체 변수는 총 40바이트의 메모리를 할당합니다.
그런데 각 멤버에 저장하는 값이 0과 1뿐이라면 실제 사용하는 공간은 1비트뿐이므로
대부분의 공간을 낭비하게 됩니다.
이런 경우 '비트 필드 구조체'를 활용할 수 있습니다.
비트 필드 구조체는 멤버의 크기를 비트 단위로 설정할 수 있습니다.
바이트 단위로 멤버의 크기를 설정하던 기존 구조체와는 다릅니다.
비트 필드 구조체의 형식과 사용법은 예제를 통해 살펴보겠습니다.
#include <stdio.h>
struct children
{
unsigned int son : 2;
unsigned int daughter : 2;
unsigned int pet : 3;
};
void main(void)
{
struct children my = { 1, 2, 3 };
int sum;
printf("struct children의 크기 : %d바이트\n", sizeof(my));
sum = my.son + my.daughter + my.pet;
printf("자식 수 : %d\n", sum);
}
/*
실행결과
struct children의 크기 : 4바이트
자식수 : 6
*/
위 코드에서 먼저 눈에 띄는 곳이 있습니다.
struct children
{
unsigned int son : 2;
unsigned int daughter : 2;
unsigned int pet : 3;
};
멤버의 이름 뒤로 ' : (숫자)' 가 붙었습니다. 이는 해당 멤버가 사용할 비트의 수를 나타냅니다.
따라서 son은 2비트, daughter도 2비트, pet은 3비트를 가집니다.
2비트는 0~3까지, 3비트는 0~7까지 저장할 수 있습니다.
unsigned가 아닌 signed의 경우 음수도 저장할 수 있지만 부호 비트의 처리 방식이 시스템마다 다를 수 있기 때문에
주로 unsigned를 사용합니다.
비트 필드 구조체의 변수 선언과 초기호, 멤버에 접근하는 방식은 일반 구조체와 같습니다.
하지만 배열을 멤버로 선언하거나 멤버의 주소를 직접 구하는 일은 불가능합니다.
따라서 키보드로 멤버에 직접 값을 입력하려는 경우 별도의 다른 변수에 임시 저장 후 해당 값을 대입해야 합니다.
멤버의 자료형은 정수형만 사용가능하며 멤버가 가질 수 있는 최대 비트 수를 결정합니다.
위의 예제에서는 자료형이 int이므로 최대 32비트까지 사용할 수 있습니다.
비트 필드 구조체의 크기는 어떻게 구해질까요?
비트 필드 구조체의 크기는 멤버의 자료형과 비트 수에 따라 결정됩니다.
방식은 다음과 같습니다.
위의 예제의 경우 멤버 3개 모두 int형으로 선언되어 있습니다.
비트 필드 구조체는 이 자료형의 크기를 기반으로 크기를 계산합니다.
int형으로 선언 되었으므로 우선 이 구조체는 4바이트의 크기를 가집니다.
그리고 메모리를 읽는 단위도 4바이트 단위가 됩니다.
멤버는 각각 2비트, 2비트, 3비트를 갖습니다. 해당 비트만큼 int형의 32개의 비트를 하나씩 채워갑니다.
멤버의 비트를 다 채워도 7비트까지만 차고 32비트를 넘지 않습니다.
따라서 해당 구조체의 크기는 4바이트가 됩니다.
만약 비트를 채우다가 32개 비트를 넘기면 새로운 int형 32비트 공간이 만들어지며 그 공간을 나머지 비트가 채웁니다.
그렇게 되면 그 구조체의 크기는 8바이트가 됩니다.
만약 3개의 멤버가 char형으로 선언되었다면 어떨까요?
struct children
{
unsigned char son : 2;
unsigned char daughter : 2;
unsigned char pet : 3;
};
멤버 모두가 char형으로 선언되었습니다. 따라서 우선 1바이트 공간이 할당됩니다.
멤버들의 비트를 다 더해도 총 7비트로 8비트가 넘지 않으므로 새로운 char공간은 생기지 않습니다.
최종적으로 이 구조체의 크기는 1바이트가 됩니다.
만약 pet멤버의 비트 수가 5였다면, 앞에서 총 4비트를 채우고 남은 4비트에 pet의 5비트를 채울 수 없으므로
pet의 자료형인 char, 즉, 1바이트 공간을 새로 할당하고 그 공간의 비트를 채우게 됩니다.
그렇게 되면 총 char형 공간이 2개 할당되었으므로 이 구조체의 크기는 2바이트가 됩니다.
그런데 만약에 세 개의 변수가 같은 자료형으로 선언되지 않고 다르다면 어떨까요?
struct children
{
unsigned char son : 2;
unsigned int daughter : 2;
unsigned char pet : 3;
};
먼저 첫 멤버가 char형으로 선언되어 있으므로 우선 1바이트의 공간을 할당합니다.
그리고 메모리 단위를 1바이트로 설정합니다.
이제 할당된 1바이트의 8비트에 son 변수 2비트를 채웁니다.
그 다음 daughter의 비트를 채우려고 보니까 이 멤버는 char가 아닌 int형으로 선언되어 있습니다.
서로 자료형이 다르기 때문에 char형의 남은 비트에 daughter의 비트를 채울 수는 없습니다.
따라서 int형 의 4바이트 공간을 새로 마련해야 합니다.
그리고 메모리 단위도 1바이트에서 4바이트로 수정합니다.
그리고 앞서 할당된 1바이트의 공간 뒤에 3바이트의 패딩 바이트를 추가하고 이어서 int형 4바이트를 할당합니다.
이로서 총 메모리 크기는 8바이트가 되었습니다.
daughter은 새로 할당된 int형 바이트에 자기 비트를 채웁니다.
그 다음으로 pet의 비트를 채울 차례입니다. 그런데 이번엔 pet의 자료형이 char로 int형이 아닙니다.
따라서 char형 공간을 다시 새로 할당해야 합니다. 그리고 새로 할당된 char형 공간에 자신의 비트를 채웁니다.
멤버의 저장이 모두 끝나면 모양을 이쁘게 만들어야 합니다.
메모리 단위가 4였으므로 현재 메모리 크기 9바이트는 이쁘지 않습니다. 여기에 3바이트의 패딩바이트를 추가합니다.
이로써 해당 구조체의 크기는 총 12바이트가 되었습니다.
다음 시간엔 '구조체 활용, 공용체, 열거형'에 대해 배우겠습니다.
'공부 일지 > C언어 공부 일지' 카테고리의 다른 글
사용자 정의 자료형 실전 문제1 (0) | 2021.01.31 |
---|---|
구조체 활용, 공용체, 열거형 (0) | 2021.01.31 |
사용자 정의 자료형 (0) | 2021.01.29 |
동적 메모리 할당 및 활용 관련 문제2 (0) | 2021.01.28 |
동적 메모리 할당 및 활용 관련 문제1 (0) | 2021.01.28 |