Ich habe diese Struktur definiert:
typedef struct
{
char A:3;
char B:3;
char C:3;
char D:3;
char E:3;
} col;
Das sizeof(col)
gibt mir die Ausgabe von 3, aber sollte es nicht 2 sein? Wenn ich nur ein Element kommentiere, sizeof
ist das 2. Ich verstehe nicht warum: Fünf Elemente mit 3 Bits entsprechen 15 Bits, und das sind weniger als 2 Bytes.
Gibt es eine "interne Größe" bei der Definition einer Struktur wie dieser? Ich brauche nur eine Klarstellung, weil ich von meiner bisherigen Vorstellung von der Sprache eine Größe von 2 Byte erwartet habe, nicht von 3.
signed char
oderunsigned char
nicht, ohne in der Dokumentation zu sehen, ob der Compiler 'plain'char
in einem Bitfeld als signiert oder nicht signiert behandelt, nicht sagen können und die Entscheidung (theoretisch) von der Entscheidung darüber abweichen kann, ob 'plain'char
ist signiert oder nicht signiert, wenn es außerhalb eines Bitfelds verwendet wird._Bool
,signed int
,unsigned int
oder eine andere Implementierung definierte Art. Die Verwendungchar
fällt daher in die Kategorie "anderer implementierungsdefinierter Typ".Antworten:
Da Sie
char
den zugrunde liegenden Typ für Ihre Felder verwenden, versucht der Compiler, Bits nach Bytes zu gruppieren. Da nicht mehr als acht Bits in jedes Byte eingefügt werden können, können nur zwei Felder pro Byte gespeichert werden.Die Gesamtsumme der von Ihrer Struktur verwendeten Bits beträgt 15, sodass die ideale Größe für so viele Daten a wäre
short
.Der obige Code (für eine 64-Bit-Plattform wie meine) ergibt tatsächlich
2
die zweite Struktur. Für alles, was größer als a istshort
, füllt die Struktur nicht mehr als ein Element des verwendeten Typs, sodass die Struktur für dieselbe Plattform die Größe vier fürint
, acht fürlong
usw. hat.quelle
char
undshort
?char
nicht signiert sind…Da Sie kein Bitpaketfeld haben können, das sich über die minimale Ausrichtungsgrenze (die 1 Byte beträgt) erstreckt, werden sie wahrscheinlich wie gepackt
(Die Reihenfolge der Felder / Auffüllungen innerhalb desselben Bytes ist nicht beabsichtigt, sondern soll Ihnen nur die Idee geben, da der Compiler sie so festlegen kann, wie er es bevorzugt.)
quelle
Die ersten beiden Bitfelder passen in ein einzelnes
char
. Der dritte kann nicht dazu passenchar
und braucht einen neuen. 3 + 3 + 3 = 9, was nicht in ein 8-Bit-Zeichen passt.Das erste Paar nimmt also a
char
, das zweite Paar achar
und das letzte Bitfeld ein dritteschar
.quelle
Bei den meisten Compilern können Sie das Auffüllen steuern, z
#pragma
. B. mit s . Hier ist ein Beispiel mit GCC 4.8.1:Beachten Sie, dass das Standardverhalten des Compilers aus einem bestimmten Grund vorliegt und wahrscheinlich zu einer besseren Leistung führt.
quelle
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:
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 eigenenchar
Feld befinden würden ). Wenn allechar
Deklarationen durch ersetztshort
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:
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.
quelle