Chociaż norma ANSI C zbyt mało określa, jak upakowane są pola bitów, aby zapewnić jakąkolwiek znaczącą przewagę nad „kompilatorami mogą pakować pola bitowe w dowolny sposób, jak uznają to za stosowne”, to jednak w wielu przypadkach zabrania kompilatorom pakowania rzeczy w najbardziej efektywny sposób.
W szczególności, jeśli struktura zawiera pola bitowe, kompilator musi przechowywać ją jako strukturę, która zawiera jedno lub więcej anonimowych pól pewnego „normalnego” typu pamięci, a następnie logicznie podzielić każde takie pole na części składowe pola bitowego. Zatem biorąc pod uwagę:
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;
Jeśli unsigned char
ma 8 bitów, kompilator musiałby przydzielić cztery pola tego typu i przypisać dwa pola bitowe do wszystkich oprócz jednego (które znajdowałoby się we char
własnym polu). Gdyby wszystkie char
deklaracje zostały zastąpione przez short
, byłyby dwa pola typu short
, z których jedno zawierałoby pięć pól bitowych, a drugie zawierałoby pozostałe dwa.
Na procesorze bez ograniczeń wyrównania dane można by układać wydajniej, używając unsigned short
dla pierwszych pięciu pól i unsigned char
dla ostatnich dwóch, przechowując siedem trzybitowych pól w trzech bajtach. Chociaż powinno być możliwe przechowywanie ośmiu trzy-bitowych pól w trzech bajtach, kompilator mógłby zezwolić na to tylko wtedy, gdyby istniał trzy bajtowy typ liczbowy, który mógłby być użyty jako typ „pola zewnętrznego”.
Osobiście uważam, że pola bitowe są zdefiniowane jako zasadniczo bezużyteczne. Jeśli kod musi działać z danymi spakowanymi binarnie, powinien wyraźnie zdefiniować lokalizacje przechowywania rzeczywistych typów, a następnie użyć makr lub innych takich środków, aby uzyskać dostęp do ich bitów. Byłoby pomocne, gdyby C obsługiwał składnię taką jak:
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;
Taka składnia, jeśli jest dozwolona, umożliwiłaby kodowi używanie pól bitowych w sposób przenośny, bez względu na rozmiary słów lub porządek bajtów (foo0 znajdowałby się w trzech najmniej znaczących bitach f1, ale te mogłyby być przechowywane w niższy lub wyższy adres). Jednak bez takiej funkcji makra są prawdopodobnie jedynym przenośnym sposobem obsługi takich rzeczy.