ANSI C 표준은 "컴파일러가 비트 필드를 패킹 할 수 있지만 적합하다고 판단되는 경우"에 비해 상당한 이점을 제공하기 위해 비트 필드가 패킹되는 방법에 대해 너무 적게 지정하지만, 그럼에도 불구하고 많은 경우 컴파일러가 가장 효율적인 방식으로 패킹하는 것을 금지합니다.
특히 구조에 비트 필드가 포함 된 경우 컴파일러는이를 "일반"저장 유형의 하나 이상의 익명 필드를 포함하는 구조로 저장 한 다음 이러한 필드를 구성 비트 필드 부분으로 논리적으로 세분화해야합니다. 따라서 주어진 :
unsigned char foo1: 3;
unsigned char foo2: 3;
unsigned char foo3: 3;
unsigned char foo4: 3;
unsigned char foo5: 3;
unsigned char foo6: 3;
unsigned char foo7: 3;
경우 unsigned char
8 비트, 컴파일러는 해당 유형의 네 개의 필드를 할당하고의 (a 될 것이다 제외한 모든 하나에 두 개의 비트 필드를 지정해야 할 것입니다 char
자신의 필드). 모든 char
선언이로 대체 된 경우 short
유형의 필드가 두 개있을 것 short
입니다. 그 중 하나는 5 개의 비트 필드를 보유하고 다른 하나는 나머지 2 개를 보유합니다.
정렬 제한이없는 프로세서 unsigned short
에서는 처음 5 개 필드와 unsigned char
마지막 2 개 필드를 사용하여 3 바이트에 7 개의 3 비트 필드를 저장 함으로써 데이터를보다 효율적으로 배치 할 수 있습니다 . 8 개의 3 비트 필드를 3 바이트로 저장할 수 있어야하지만 컴파일러는 "외부 필드"유형으로 사용할 수있는 3 바이트 숫자 유형이있는 경우에만이를 허용 할 수 있습니다.
개인적으로 나는 기본적으로 쓸모없는 것으로 정의 된 비트 필드를 고려합니다. 코드가 이진으로 압축 된 데이터로 작업해야하는 경우 실제 유형의 저장 위치를 명시 적으로 정의한 다음 매크로 또는 기타 이러한 수단을 사용하여 비트에 액세스해야합니다. C가 다음과 같은 구문을 지원한다면 도움이 될 것입니다.
unsigned short f1;
unsigned char f2;
union foo1 = f1:0.3;
union foo2 = f1:3.3;
union foo3 = f1:6.3;
union foo4 = f1:9.3;
union foo5 = f1:12.3;
union foo6 = f2:0.3;
union foo7 = f2:3.3;
이러한 구문은 허용되는 경우 코드가 단어 크기 나 바이트 순서에 관계없이 이식 가능한 방식으로 비트 필드를 사용할 수 있도록합니다 (foo0은 f1의 최하위 비트 3 개에 속하지만 더 낮거나 더 높은 주소). 그러나 이러한 기능이 없으면 매크로가 이러한 작업을 수행하는 유일한 이식 방법 일 수 있습니다.