Warum ist die Größe der gepackten Struktur 5 statt 4 Bytes hier?

8

Siehe Online-Beispiel: Ideone-Beispiel

%Vor%

Warum würde der Compiler die Größe der Struktur hier als 5 Bytes anstatt als 4 melden? Es sollte 32 Bits enthalten.

    
Primož Kralj 01.04.2015, 07:15
quelle

4 Antworten

5

Das liegt an der Speicherausrichtung: Der Compiler startet canFlags nicht in der Mitte eines Bytes, sondern startet ihn am Anfang des nächsten Bytes (wahrscheinlich *). Sie haben also vier Bytes für Ihre erste Vereinigung und ein Byte für canFlags .

Wenn Sie zum Beispiel canFlags in die Union verschoben haben, hätte es (wahrscheinlich *) die Größe 4:

%Vor%

Aktualisiertes Beispiel auf ideone . Offensichtlich ist diese spezifische Veränderung wahrscheinlich nicht das, was Sie wollen; Ich zeige gerade, dass das Problem ein neues Feld nicht an einer Bytegrenze beginnt.

* "wahrscheinlich", weil es letztendlich am Compiler liegt.

    
T.J. Crowder 01.04.2015, 07:18
quelle
6

Das Problem ist, dass __attribute__((packed)) kein bitweises Packen durchführt. Es garantiert nur, dass zwischen struct -Membern kein Padding vorhanden ist. Sie können dieses einfachere Beispiel ausprobieren, bei dem die Größe auch als 5 angegeben wird:

%Vor%

Bitweises Packen ist nur für Bitfeld-Mitglieder möglich. Sie müssen Ihre Struktur so umstrukturieren, dass sie eine Union einer Struktur mit Bitfeldern MessageID / Priorität / canFlags und einer Struktur mit Bitfeldern rowID / canFlags ist. Mit anderen Worten, Sie müssen entweder eine Duplizierung durchführen oder auf Accessor-Makros oder Elementfunktionen zurückgreifen.

    
user4815162342 01.04.2015 07:27
quelle
1

Die Daten werden im Computerspeicher unter Verwendung der Datenstrukturausrichtung angeordnet und abgerufen. Welches hat zwei verwandte Probleme

  1. Ausrichtung
  2. Auffüllen

Wenn eine Schreiboperation vom Computer ausgeführt wird, schreibt sie normalerweise in mehrere Bytes (für 32-Bit-Systeme). Ein Grund für diesen Akt ist das Ziel, die Leistung zu steigern. Wenn Sie also eine Datenstruktur schreiben, die zuerst eine 1-Byte-Variable und dann 4 Byte variable Daten enthält, führt sie nach den ersten 1-Byte-Daten eine Auffüllung durch, um sie auf 32-Bit-Grenzen auszurichten.

%Vor%

In der obigen Datenstruktur verwenden Sie __attribute__ ((packed)) , was bedeutet, dass kein Padding vorhanden ist. Uint32_t ist also 4 Bytes, aber Sie haben 26 Bits und 3 Bits für die Priorität. Jetzt, da Sie beide Variablen in einer Struktur haben, reserviert es 32 statt 29 Bits, so dass die Informationen Ihrer ersten Struktur an Grenzen ausgerichtet sind.

Jetzt für canFlags Es braucht noch weitere Bytes. Also macht das 5 Bytes statt 4.

    
Yasir Majeed 01.04.2015 07:43
quelle
0

Um die Bits in einigen Compilern "zusammenzuführen", müssen alle Elemente vom selben Typ sein. Also mach es uint32_t wo du nun uint8_t hast - das scheint im Compiler nicht der Fall zu sein IdeOne benutzt tho '

[Egal was es ist, es liegt immer noch an dem Compiler, wie es die Bits zusammenführt, so ist es die einzige Möglichkeit, absolut zu garantieren, dass Ihre Daten als 32 Bits gespeichert werden, ist ein einzelnes uint32_t zu verwenden und eine Klasse zu deklarieren macht das relevante Verschieben und Anordnen, um den Wert zu manipulieren - die einzige Garantie, die Sie haben, ist, dass ein Element in Ihrer Struktur mindestens so viele Bits hat, wie Sie gefordert haben]

Wie bereits erwähnt, können Sie keine neue Struktur auf einer anderen als einer Bytegrenze beginnen. Ich habe es behoben, indem ich eine zweite Struktur in der Union habe, so: Ссылка

%Vor%     
Mats Petersson 01.04.2015 07:18
quelle

Tags und Links