Was bedeutet ein Doppelpunkt in einer Struct-Deklaration, z. B. :1, :7, :16 oder :32?

Lesezeit: 4 Minuten

Was bedeutet ein Doppelpunkt in einer Struct Deklaration z B 1
derrdji

Was bedeutet der folgende C++-Code?

unsigned char a : 1; 
unsigned char b : 7;

Ich denke, es erstellt zwei Zeichen a und b, und beide sollten ein Byte lang sein, aber ich habe keine Ahnung, was der Teil “: 1” und “: 7” tut.

1647135009 446 Was bedeutet ein Doppelpunkt in einer Struct Deklaration z B 1
paxdiablo

Die 1 und die 7 sind Bitgrößen, um den Bereich der Werte zu begrenzen. Sie sind typischerweise in Strukturen und Gewerkschaften zu finden. Beispielsweise auf einigen Systemen (abhängig von char Breite und Verpackungsregeln usw.), der Code:

typedef struct {
    unsigned char a : 1;
    unsigned char b : 7;
} tOneAndSevenBits;

erzeugt einen 8-Bit-Wert, ein Bit für a und 7 Bit für b.

Wird normalerweise in C verwendet, um auf “komprimierte” Werte wie ein 4-Bit-Nibble zuzugreifen, das in der oberen Hälfte eines 8-Bit-Zeichens enthalten sein kann:

typedef struct {
    unsigned char leftFour  : 4;
    unsigned char rightFour : 4;
} tTwoNybbles;

Für die Sprachjuristen unter uns erklärt der Abschnitt 9.6 des C++11-Standards dies ausführlich, leicht paraphrasiert:


Bitfelder [class.bit]

Ein Member-Declarator des Formulars

Kennungopt Attributbezeichneropt : konstanter Ausdruck

spezifiziert ein Bitfeld; seine Länge wird durch einen Doppelpunkt vom Bitfeldnamen abgesetzt. Die Wahl Attributbezeichner bezieht sich auf die deklarierte Entität. Das Bitfeldattribut ist nicht Teil des Typs des Klassenmembers.

Die konstanter Ausdruck muss ein ganzzahliger konstanter Ausdruck mit einem Wert größer oder gleich Null sein. Der Wert des ganzzahligen konstanten Ausdrucks kann größer sein als die Anzahl der Bits in der Objektdarstellung des Typs des Bitfelds; in solchen Fällen werden die zusätzlichen Bits als Füllbits verwendet und nehmen nicht an der Wertdarstellung des Bitfelds teil.

Die Zuordnung von Bitfeldern innerhalb eines Klassenobjekts ist implementierungsdefiniert. Die Ausrichtung von Bitfeldern ist implementierungsdefiniert. Bitfelder werden in eine adressierbare Zuordnungseinheit gepackt.

Notiz: Bitfelder überspannen Zuordnungseinheiten auf einigen Maschinen und nicht auf anderen. Bitfelder werden auf einigen Maschinen von rechts nach links zugewiesen, auf anderen von links nach rechts. – Schlussbemerkung

  • Genau genommen würden sie in reinem C nicht verwendet werden unsigned char. C erlaubt nur int, signed int und unsigned int in Bitfeld-Deklarationen. C99 ergänzt _Bool. unsigned char ist kein gültiger Typ für Bitfield in C.

    – Ant

    22. Oktober 2009 um 5:07 Uhr

  • Das ist ein Implementierungsproblem, zumindest in c1x: 6.7.2.1 para4 Ein Bitfeld muss einen Typ haben, der eine qualifizierte oder nicht qualifizierte Version von _Bool, signed int, unsigned int oder ist ein anderer implementierungsdefinierter Typ.

    – paxdiablo

    22. Oktober 2009 um 5:30 Uhr

  • @paxdiablo: Ja, aber das Bit “irgendein anderer implementierungsdefinierter Typ” ist wirklich überflüssig, da die Implementierung die Sprache immer so erweitern darf, wie sie es für richtig hält, ohne eine ausdrückliche Erlaubnis im spezifischen Abschnitt des Standards. Die AC-Implementierung kann Pascal- und Fortran-Code innerhalb von C-Code kompilieren – niemand verbietet es ihr, dies zu tun. Dennoch wäre es seltsam, Fortran-Code aus diesem Grund als möglicherweise gültigen C-Code zu diskutieren. Dasselbe gilt auch für diesen “implementierungsdefinierten Typ”.

    – Ant

    22. Oktober 2009 um 6:04 Uhr

  • @AndreyT: Diese Art der Formulierung ist jedoch weit verbreitet. es notiert gemeinsame, sinnvolle Erweiterungen.

    – MSalter

    22. Oktober 2009 um 9:23 Uhr

  • @AndreyT, das Bit “implementierungsdefinierter Typ” ist hier nicht ganz überflüssig. Wenn dies nicht der Fall wäre, müsste der Compiler aufgrund einer Einschränkungsverletzung eine Diagnose ausgeben. Das Ding “implementierungsdefinierter Typ” gewährt dem Compiler die Akzeptanz anderer Typen, ohne eine Diagnose zu geben.

    – Johannes Schaub – litb

    22. Oktober 2009 um 10:51 Uhr

Ich glaube, das wären Bitfields.

  • Nicht sicher, es sei denn, es ist die Kürze oder Unsicherheit, aber hier ist eine positive Bewertung, da (1) Sie technisch korrekt sind; und (2) um die Liebe zu teilen 🙂

    – paxdiablo

    22. Oktober 2009 um 4:19 Uhr

Genau genommen muss ein Bitfeld ein int, unsigned int oder _Bool sein. Obwohl die meisten Compiler jeden ganzzahligen Typ akzeptieren.

Siehe C11 6.7.2.1:

Ein Bitfeld muss einen Typ haben, der eine qualifizierte oder nicht qualifizierte Version von _Bool, signed int, unsigned int oder einem anderen implementierungsdefinierten Typ ist.

Ihr Compiler wird wahrscheinlich 1 Byte Speicherplatz zuweisen, aber es steht Ihnen frei, mehr zu greifen.

Siehe C11 6.7.2.1:

Eine Implementierung kann jede adressierbare Speichereinheit zuweisen, die groß genug ist, um ein Bitfeld zu halten.

Die Einsparungen ergeben sich, wenn Sie mehrere Bitfelder haben, die nacheinander deklariert werden. In diesem Fall wird der zugewiesene Speicher nach Möglichkeit gepackt.

Siehe C11 6.7.2.1:

Wenn genügend Platz verbleibt, soll ein Bitfeld, das in einer Struktur unmittelbar auf ein anderes Bitfeld folgt, in benachbarte Bits derselben Einheit gepackt werden. Wenn nicht genügend Platz verbleibt, ist es implementierungsdefiniert, ob ein Bitfeld, das nicht passt, in die nächste Einheit eingefügt wird oder benachbarte Einheiten überlappt.

995560cookie-checkWas bedeutet ein Doppelpunkt in einer Struct-Deklaration, z. B. :1, :7, :16 oder :32?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy