___ tag123c ___ C ist eine universelle Computerprogrammiersprache, die für Betriebssysteme, Bibliotheken, Spiele und andere Hochleistungsanwendungen verwendet wird. Dieses Tag sollte bei allgemeinen Fragen zur C-Sprache verwendet werden, wie in der Norm ISO 9899: 2011 definiert. Fügen Sie ggf. ein versionsspezifisches Tag wie c99 oder c90 für Fragen zu älteren Sprachstandards hinzu. C unterscheidet sich von C ++ und es sollte nicht mit dem C ++ - Tag kombiniert werden, wenn ein rationaler Grund fehlt.
___ qstntxt ___
Ich habe den Code kompiliert,
%Vor%
und die Ausgabe war etwas unerwartet.
%Vor%
Wie im C11-Entwurf angegeben,
... Wenn genug Platz bleibt, wird ein Bitfeld, das unmittelbar einem anderen Bitfeld in einer Struktur folgt, in benachbarte Bits derselben Einheit gepackt ...
Ich habe erwartet, dass es in 4 Bytes passt, da ich einen 32-Bit-Compiler verwendet habe. Speziell verwendete ich gcc (tdm-1) 5.1.0. Ist es gegen den Standard?
BEARBEITEN:
Das Ersetzen von int
s in _Bool
funktioniert wie erwartet ... Ich bin nicht sicher warum ...
BEARBEITEN:
In gcc 5.4.0 funktioniert der Code wie erwartet. Der entscheidende Punkt dieser Frage ist , warum der nachgestellte %code% s und der %code% nicht in den ersten passen. Ich denke, ich habe nicht viele Annahmen über die Implementierung gemacht (außer %code% ist mindestens 4 Bytes, was akzeptabel ist), und Ich spreche hier über das garantierte Verhalten von C durch den C-Standard . Daher kann ich nicht einigen Kommentaren zustimmen.
Dies sind Bitfelder. Einem "erwarteten" Output steht nicht viel im Wege, da diese vom Standard sehr schlecht spezifiziert sind. Außerdem neigen Compiler dazu, wenig Unterstützung für sie zu haben.
Um zu beginnen, sagt der komplette Abschnitt, den Sie zitieren (6.7.2.1/11):
Eine Implementierung kann jede adressierbare Speichereinheit groß zuweisen
genug, um ein Bitfeld zu halten. Wenn genug Platz bleibt, ein Bit-Feld, das
unmittelbar folgt ein weiteres Bit-Feld in einer Struktur soll gepackt werden
in benachbarte Bits derselben Einheit. Wenn nicht genügend Platz bleibt,
ob ein Bitfeld, das nicht passt, in die nächste Einheit oder übernommen wird
überlappt benachbarte Einheiten ist implementierungsdefiniert. Die Reihenfolge von
Zuweisung von Bitfeldern innerhalb einer Einheit (höher oder niedrig oder
niedriger Ordnung zu hoher Ordnung) ist implementierungsdefiniert. Die Ausrichtung von
die adressierbare Speichereinheit ist nicht spezifiziert.
All dies bedeutet, dass Sie so gut wie keine Annahmen darüber machen können, wie die Bits im Speicher landen. Sie können nicht wissen, wie der Compiler die Ausrichtung anordnet, Sie können die Bit-Reihenfolge der Bits nicht kennen, Sie können die Signedness nicht kennen, Sie können die Endianess nicht kennen.
Wenn %code% und %code% in dieselbe "Speichereinheit" verschmelzen ... nun, warum sollten sie? Sie sind inkompatible Typen. Der C-Standard erwähnt nicht, was passieren wird, wenn Sie zwei benachbarte Bitfelder von inkompatiblen Typen haben - es ist offen für subjektive Interpretation. Ich vermute, dass es verschiedene Aliasing-Probleme geben wird.
Es ist also völlig in Ordnung, wenn der Compiler all diese in separate "Speichereinheiten" legt. Wenn Sie Objekte des gleichen Typs nebeneinander platzieren, würde ich jedoch erwarten, dass sie sie zusammenführen oder der zitierte Teil würde keinen Sinn ergeben. Zum Beispiel würde ich Größe 8 von folgendem erwarten:
%Vor%
Nun, was Sie tun sollten, wenn Sie sich deterministisch verhalten wollen: Portabler Code besteht darin, Bitfelder aus dem Fenster zu werfen und stattdessen bitweise Operatoren zu verwenden. Sie sind 100% deterministisch und portabel.
Angenommen, Sie möchten eigentlich keine mysteriösen Zahlenfelder mit Vorzeichen, auf die Ihr ursprünglicher Code hinweist, dann:
%Vor%
Entwerfe dann Setter / Getter-Funktionen oder Makros, die die Daten von diesem 32-Bit-Chunk setzen / abrufen. Wenn Sie richtig geschrieben sind, können Sie einen solchen Code endianess-unabhängig machen.
Ich vermute, dass der Compiler die Bitfelder " %code% " und " %code% " als unterschiedliche Typen behandelt. Es kombiniert also alle %code% Bitfelder zusammen und die %code% Bitfelder zusammen, aber kombiniert %code% und %code% Bitfelder nicht. Also würde die Struktur so zusammengesetzt werden, um 12 Bytes zu machen:
%Vor%
BEARBEITEN: Dieser Absatz aus dem C-Standard von 2011 könnte so interpretiert werden, dass %code% -Bitfelder unterschiedlich wirken:
6.7.2.1 Struktur- und Vereinigungsspezifizierer
Ein Bitfeld wird als vorzeichenbehafteter oder vorzeichenloser Integertyp interpretiert, der aus der angegebenen Anzahl von Bits besteht. Wenn der Wert 0 oder 1 in einem Bitfeld ungleich Null des Typs _Bool gespeichert wird, muss der Wert des Bitfelds mit dem gespeicherten Wert übereinstimmen. Ein _Bool-Bitfeld hat die Semantik eines _Bool.
Wenn ein %code% Bit-Feld die Semantik eines _Bool hat, dann hat der Implementierer das vielleicht so interpretiert, dass "Act like %code% entspricht %code% "
Ein schneller Test hier scheint diese Theorie zu bestätigen.