Obwohl der ANSI C-Standard zu wenig darüber spezifiziert, wie Bitfelder gepackt werden, um einen signifikanten Vorteil gegenüber "Compilern, die Bitfelder packen dürfen, wie sie es für richtig halten" zu bieten, verbietet er Compilern in vielen Fällen, Dinge auf die effizienteste Weise zu packen.
Insbesondere wenn eine Struktur Bitfelder enthält, muss ein Compiler sie als Struktur speichern, die ein oder mehrere anonyme Felder eines "normalen" Speichertyps enthält, und dann jedes dieser Felder logisch in seine konstituierenden Bitfeldteile unterteilen. Also gegeben:
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;
Wenn unsigned char
8 Bit vorhanden sind, muss der Compiler vier Felder dieses Typs zuweisen und allen bis auf eines zwei Bitfelder zuweisen (die sich in einem eigenen char
Feld befinden würden ). Wenn alle char
Deklarationen durch ersetzt short
worden wären, gäbe es zwei Typfeldershort
Typfelder, von denen eines fünf Bitfelder und das andere die verbleibenden zwei würde.
Auf einem Prozessor ohne Ausrichtungsbeschränkungen könnten die Daten effizienter ausgelegt werden, indem unsigned short
für die ersten fünf Felder und verwendet werdenunsigned char
für die letzten zwei Felder sieben Drei-Bit-Felder in drei Bytes gespeichert werden. Während es möglich sein sollte, acht Drei-Bit-Felder in drei Bytes zu speichern, konnte ein Compiler dies nur zulassen, wenn ein numerischer Drei-Byte-Typ vorhanden war, der als Typ "äußeres Feld" verwendet werden konnte.
Persönlich halte ich Bitfelder als definiert für grundsätzlich nutzlos. Wenn Code mit binär gepackten Daten arbeiten muss, sollte er explizit Speicherorte tatsächlicher Typen definieren und dann Makros oder andere solche Mittel verwenden, um auf deren Bits zuzugreifen. Es wäre hilfreich, wenn C eine Syntax wie die folgende unterstützen würde:
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;
Eine solche Syntax würde es dem Code ermöglichen, Bitfelder auf tragbare Weise zu verwenden, ohne Rücksicht auf Wortgrößen oder Bytereihenfolgen (foo0 würde in den drei niedrigstwertigen Bits von f1 liegen, aber diese könnten im gespeichert werden niedrigere oder höhere Adresse). Ohne eine solche Funktion sind Makros jedoch wahrscheinlich die einzige tragbare Möglichkeit, mit solchen Dingen zu arbeiten.