56.0 구조체 비트 필드 사용하기
구조체 비트 필드를 사용하면 구조체 멤버를 비트 단위로 저장할 수 있음. 특히 CPU나 기타 칩의 플래그를 다루는 저수준(low level) 프로그래밍을 할 때 기본 자료형보다 더 작은 비트 단위로 값을 가져오거나 저장하는 경우가 많으므로 구조체 비트 필드가 유용하게 사용. 참고로 비트 필드는 내용이 다소 어려운데다 접할 기회가 많지 않으므로 완벽하게 이해하지 않아도 됨.
56.1 구조체 비트 필드를 만들고 사용하기
C99 표준에서는 비트 필드로 사용할 수 있는 자료형을 _Bool, signed int, unsigned int, int로 규정하고 있지만 대부분의 컴파일러에서는 모든 정수 자료형을 사용할 수 있음 보통은 비트 필드에 부호 없는(unsigned) 자료형을 주로 사용 단, 실수 자료형은 비트 필드로 사용할 수 없음.
struct 구조체이름{
정수자료형 멤버이름: 비트수;
};
#include <stdio.h>
struct Flags {
unsigned int a : 1; // a는 1비트 크기
unsigned int b : 3; // b는 3비트 크기
unsigned int c : 7; // c는 7비트 크기
};
int main()
{
struct Flags f1; // 구조체 변수 선언
f1.a = 1; // 1: 0000 0001, 비트 1개
f1.b = 15; // 15: 0000 1111, 비트 4개
f1.c = 255; // 15: 0000 1111, 비트 4개
printf("%u\n", f1.a); // 1: 1, 비트 1개만 저장됨
printf("%u\n", f1.b); // 7: 111, 비트 3개만 저장됨
printf("%u\n", f1.c); // 127: 111 1111, 비트 7개만 저장됨
return 0;
}
비트 필드에는 지정한 비트 수만큼 저장되며 나머지 비트는 버려짐.
다음과 같이 비트 필드의 각 멤버는 최하위 비트(Least Significant Bit, LSB)부터 차례대로 배치
따라서 a가 최하위 비트에 오고 나머지 멤버들은 각각 상위비트에 배치
sizeof 연산자로 Flags 비트 필드 구조체의 크기를 구해보면 4가 나옴.
#include <stdio.h>
struct Flags {
unsigned int a : 1; // a는 1비트 크기
unsigned int b : 3; // b는 3비트 크기
unsigned int c : 7; // c는 7비트 크기
};
int main()
{
printf("%d", sizeof(struct Flags)); // 4: 멤버를 unsigned int로 선언했으므로 4
return 0;
}
비트 필드의 멤버를 unsigned int로 선언했으므로 구조체의 크기는 4
만약 멤버를 unsigned short로 선언하면 구조체의 크기는 2
다음과 같이 비트 필드의 멤버를 선언하는 자료형보다 큰 비트 수는 지정할 수 없습니다.
struct Flags {
unsigned int a : 37; // 컴파일 에러. unsigned int보다 큰 비트 수는 지정할 수 없음
unsigned int b : 3;
unsigned int c : 7;
};
56.2 비트 필드와 공용체를 함께 사용하기
보통 사람이 코드에서 값을 지정할 때는 비트 필드를 사용하지만 CPU나 칩에 값을 설정할 때는 모든 비트를 묶어서 한꺼번에 저장 비트 필드의 값을 한꺼번에 사용할 수 있도록 비트 필드와 공용체를 함께 사용
#include <stdio.h>
struct Flags {
union {
struct {
unsigned int a : 3; // a는 1비트 크기
unsigned int b : 2; // b는 3비트 크기
unsigned int c : 7; // c는 7비트 크기
unsigned int 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;
}
먼저 비트 필드로 사용할 멤버는 익명 구조체로 감싸줍니다. 그리고 비트 필드의 값을 한꺼번에 접근할 수 있도록 unsigned short형 멤버를 선언하고 익명 공용체로 감싸줍니다.
지금까지 비트 필드에 대해 배웠는데 비트 단위로 값을 다루다보니 눈에 잘 들어오지 않았습니다. 비트 필드는 쓸 일이 많지 않으므로 이런 기능이 있다 정도로만 알아두면 됩니다.
'C > C언어 코딩도장' 카테고리의 다른 글
UNIT 58 자료형 변환하기 (0) | 2022.03.15 |
---|---|
UNIT 57 열거형 사용하기 (0) | 2022.03.14 |
UNIT 55 구조체와 공용체 활용하기 (0) | 2022.03.13 |
UNIT 54 공용체 사용하기 (0) | 2022.03.13 |
UNIT 53 구조체 배열 사용하기 (0) | 2022.03.12 |