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.
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.
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.