C-Bitfelder

Zusätzlich zu Deklaratoren für Member einer Struktur oder Union kann ein Strukturdeklarator auch eine festgelegte Anzahl von Bits sein, die als „Bitfeld“ bezeichnet wird. Die Länge des Bitfelds wird durch einen Doppelpunkt vom Deklarator des Namens getrennt. Ein Bitfeld wird als Ganzzahltyp interpretiert.

Syntax

struct-declarator:
declarator
type-specifierdeclaratoropt:constant-expression

constant-expression gibt die Breite des Felds in Bits an. Der type-specifier für den declarator muss unsigned int, signed int oder int sein, und constant-expression muss ein nicht negativer Ganzzahlwert sein. Falls der Wert 0 (null) ist, weist die Deklaration keinen declarator auf. Arrays aus Bitfeldern, Zeiger auf Bitfelder und Funktionen, die Bitfelder zurückgeben, sind nicht zulässig. Der optionale declarator benennt das Bitfeld. Bitfelder können nur als Teil einer Struktur deklariert werden. Der address-of-Operator (&) kann nicht auf Bitfeldkomponenten angewendet werden.

Auf unbenannte Bitfelder kann nicht verwiesen werden, und deren Inhalt zur Laufzeit ist unvorhersehbar. Sie können als "Dummy"-Felder zu Ausrichtungszwecken verwendet werden. Ein unbenanntes Bitfeld, dessen Breite auf 0 festgelegt ist, garantiert, dass der Speicher für das in struct-declaration-list nachfolgende Element an einer int-Grenze beginnt.

Die Anzahl der Bits in einem Bitfeld muss kleiner oder gleich der Größe des zugrunde liegenden Typs sein. Beispielsweise sind die folgenden beiden Anweisungen nicht zulässig:

short a:17;        /* Illegal! */
int long y:33;     /* Illegal! */

In diesem Beispiel wird ein zweidimensionales Array von Strukturen mit dem Namen screen definiert.

struct
{
    unsigned short icon : 8;
    unsigned short color : 4;
    unsigned short underline : 1;
    unsigned short blink : 1;
} screen[25][80];

Das Array enthält 2.000 Elemente. Jedes Element ist eine einzelne Struktur, die vier Bitfeldmember enthält: icon, color, underline und blink. Die Größe der einzelnen Strukturen beträgt zwei Bytes.

Bitfelder weisen die gleiche Semantik wie der Ganzzahltyp auf. Ein Bitfeld in Ausdrücken wird auf genau die gleiche Weise verwendet wie eine Variable des gleichen Basistyps. Dies gilt unabhängig davon, wie viele Bits das Bitfeld aufweist.

Microsoft-spezifisch

Bitfelder, die als int definiert sind, werden als signed behandelt. Eine Microsoft-Erweiterung für den ANSI C-Standard erlaubt die Typen char und long (sowohl signed als auch unsigned ) für Bitfelder. Unbenannte Bitfelder mit dem Basistyp long, short oder char (signed oder unsigned) erzwingen eine Ausrichtung an einer für den Basistyp geeigneten Grenze.

Bitfelder werden innerhalb einer Ganzzahl vom niedrigstwertigen hin zum höchstwertigen Bit angeordnet. Im folgenden Code etwa

struct mybitfields
{
    unsigned short a : 4;
    unsigned short b : 5;
    unsigned short c : 7;
} test;

int main( void )
{
    test.a = 2;
    test.b = 31;
    test.c = 0;
    return 0;
}

wären die Bits von test folgendermaßen angeordnet:

00000001 11110010
cccccccb bbbbaaaa

Da die Familie der 8086-Prozessoren das niederwertige Byte ganzzahliger Werte vor dem höherwertigen Byte speichert, würde die Ganzzahl 0x01F2 im physischen Speicher als 0xF2 gefolgt von 0x01 gespeichert werden.

Mit dem ISO C99-Standard kann eine Implementierung auswählen, ob ein Bitfeld auf zwei Speicherinstanzen aufgeteilt werden darf. Sehen Sie sich diese Struktur an, in der Bitfelder mit einer Gesamtanzahl von 64 Bits gespeichert werden:

struct
{
    unsigned int first : 9;
    unsigned int second : 7;
    unsigned int may_straddle : 30;
    unsigned int last : 18;
} tricky_bits;

Eine C-Standardimplementierung könnte diese Bitfelder in zwei 32-Bit-Integern speichern. Sie könnte tricky_bits.may_straddle als 16 Bits in einem 32-Bit-Integer und als 14 Bits im nächsten 32-Bit-Integer speichern. Die Windows ABI-Konvention speichert Bitfelder in einzelnen Speicherintegern und teilt Speichereinheiten nicht auf. Der Microsoft-Compiler speichert jedes Bitfeld im obigen Beispiel so, dass es vollständig in einen 32-Bit-Integer passt. In diesem Fall werden first und second in einem Integer, may_straddle in einem zweiten Integer und last in einem dritten Integer gespeichert. Der Operator sizeof gibt 12 für eine Instanz von tricky_bits zurück. Weitere Informationen finden Sie unter Abstand und Ausrichtung von Strukturmembern.

Ende Microsoft-spezifisch

Siehe auch

Strukturdeklarationen