비트필드는 각 구조체 구성요소를 비트 단위로 나눌 수 있다.
일반적인 구조체에서 구조체 구성요소는 C가 지원하는 데이터 형태로만 나누어지는데 비해 비트필드는 비트 단위로 구성요소를 나눌 수 있기 때문에 더욱더 세밀한 데이터 조정이 가능
비트필드는 구조 내에서 사용되기 때문에 먼저 구조 유형을 선언하여야 하는데, 다음과 같은 형태로 선언.
struct bit_field { unsigned b1: 1; unsigned b2: 2; unsigned b3: 4; } x;
위를 보면 다른 구조의 정의와 같은데 구성요소의 이름 다음에 ':'를 붙이고 그 뒤에 비트의 크기를 지정하는 것이 다르다.
이때 이 구성요소는 위의 구조 내에서 딱 비트 크기 만큼의 비트 수만 차지하게 된다.
그리고 비트 필드를 사용하는 경우에 구성요소의 이름을 생략할 수 있는데, 이 경우 그 구성요소에 해당하는 비트들은 사용할 수 없게 된다(실제로 사용하지 않겠다는 의미가 된다).
또 비트 크기를 0으로 선언할 수도 있다. 이는 단어의 경계면으로 이동하여 그 다음 비트부터는 다른 바이트나 단어에 할당하라는 의미가 된다.
struct move { unsigned x: 3; unsigned y: 3; unsigned z: 0; unsigned w: 5; } m;
x는 처음 3비트를, y는 그 다음 3비트를 차지하게 되지만 z는 크기가 0이다.
따라서 z는 메모리를 차지하지 않으며 그 다음의 w를 y다음이 아닌 다음 워드(PC의 경우 짝수 바이트)에 할당하라는 의미가 된다.
따라서 m은 다음과 같은 구조를 갖게 된다.
일반적으로 하나의 비트필드의 크기는 단어의 크기를 초과할 수 없도록 되어 있으며, 단어 경계면에 걸쳐 존재할 수도 없게 되어 있다.
따라서 특정 비트필드가 단어 경계면에 존재하게 될 경우에는 위와 같이 다음 단어로 이동하는 것이 필요하게 된다.
그리고 비트 필드로 지정된 구성요소의 데이터 유형도 signed는 의미가 없기 때문에 unsigned int가 사용되며 비트 필드 형태의 배열은 사용할 수 없고 당연히 여기에 '&'연산자도 적용할 수 없다.
#include <stdio.h> struct hangeul { unsigned int s: 1; /* 부호 */ unsigned int f: 5; /* 초성 */ unsigned int m: 5; /* 중성 */ unsigned int l: 5; /* 종성 */ }; main() { unsigned char c; unsigned char c2; struct hangeul h; while ((c = getchar()) != 255) { /* unsigned char라서 -1이 아닌 255 */ h.s = ((c & 0x80) >> 7); if (h.s == 0) { printf("%c -> %dn",c,c); continue; } h.f = ((c & 0x7c) >> 2); h.m = ((c & 0x3) << 3); c2 = getchar(); h.m |= ((c2 & 0xe0) >> 5); h.l = c2 & 0x1f; printf("%c%c -> %u, %u, %un",c,c2,h.f,h.m,h.l); } }