Wenn Strukturen definiert werden, darf der Compiler Paddings (Leerzeichen ohne eigentliche Daten) hinzufügen, damit Mitglieder in Adressgrenzen fallen, auf die die CPU leichter zugreifen kann.
Auf einer 32-Bit-CPU sollten 32-Bit-Mitglieder beispielsweise bei Adressen beginnen, die ein Vielfaches von 4 Bytes sind, um effizient auf sie zugreifen zu können (Lesen und Schreiben). Die folgende Strukturdefinition fügt eine 16-Bit-Auffüllung zwischen beiden Mitgliedern hinzu, sodass das zweite Mitglied in eine richtige Adressgrenze fällt:
struct S {
int16_t member1;
int32_t member2;
};
Die Speicherstruktur der obigen Struktur in einer 32-Bit-Architektur ist (~ = Polsterung):
Beim Packen einer Struktur werden diese Paddings nicht eingefügt. Der Compiler muss mehr Code generieren (der langsamer läuft), um die nicht ausgerichteten Datenelemente zu extrahieren und auch in sie zu schreiben.
Die gleiche Struktur erscheint, wenn sie gepackt ist, im Speicher als etwas wie:
Tangentiale Frage, aber warum sollte man eine gepackte Struktur schaffen, wenn es die Dinge langsamer macht? Soll der Speicherbedarf reduziert werden?
– verdammt
12. Dezember 2017 um 6:05 Uhr
Ein Anwendungsfall: Sie werden sehr oft zum Definieren und Implementieren von Netzwerkprotokollen, Binärformaten usw. verwendet. Normalerweise möchten Sie Strukturen, die gespeichert oder über das Netzwerk gesendet werden, keine Auffüllungen hinzufügen.
– jjmontes
4. April 2018 um 14:25 Uhr
In Ihrem Beispiel sind 16 Bit + 32 Bit = 48 Bit = 12 Byte und das ist tatsächlich ein Vielfaches von 4 Byte. Warum sollte ein Compiler dann Padding anwenden?
– Sprungmann
23. Oktober 2018 um 11:19 Uhr
@Maxitj, 48 Bit sind 6 Bytes, nicht 12.
– Juliano
23. Oktober 2018 um 11:50 Uhr
@Juliano Dummkopf, war ziemlich müde, als ich diesen Beitrag gelesen habe 🙂
– Sprungmann
29. Oktober 2018 um 18:25 Uhr
NPE
Es weist den Compiler an, keine Auffüllung zwischen Mitgliedern von hinzuzufügen struct.
Ich denke, Sie meinen das Gegenteil – verpackt bedeutet, jegliche Polsterung wegzulassen und nicht hinzuzufügen.
– flolo
29. März 2011 um 13:26 Uhr
Der Link in dieser Antwort ist defekt, gibt es eine Möglichkeit zur Behebung?
– Kev
20. November 2011 um 16:41 Uhr
Detail: “Keine Auffüllung zwischen Mitgliedern hinzufügen” ist eher wie Hinzufügen Minimum Verpackung. Bestimmte Architekturen können in ausgewählten Fällen immer noch eine gewisse Auffüllung erfordern. (z.B int muss auf gerader Adressgrenze liegen, um Busfehler zu vermeiden.)
– chux – Wiedereinsetzung von Monica
12. Juli 2016 um 17:37 Uhr
Babajan
Lassen Sie mich das Konzept des Auffüllens in Strukturen und dann von gepackten Strukturen anhand eines Beispiels erläutern.
Und dann lassen Sie uns sehen, warum eine Verpackung erforderlich ist.
Polsterung:
struct eg_struct
{
unsigned char abc;
unsigned int xyz;
}
Wenn die Struktur wie oben auf einer 16-Bit-Architektur deklariert wird, wird die Variable abc würde eine Adresse zugewiesen werden. Die nächste Adresse wird nicht der Variablen zugewiesen xyzstattdessen wird ein zusätzliches Byte hinzugefügt, und dann würde der Variablen die nächste Adresse zugewiesen xyz.
Das Auffüllen macht Adressen von Mitgliedsvariablen für den Mikrocontroller leicht zugänglich. Der Nachteil sind zusätzliche unnötige Bytes, die ins Bild kommen.
Verpackung:
Wenn die gleiche Struktur mit dem Attribut „packed“, wird das zusätzliche Byte nicht nach der Variablen hinzugefügt abc.
Lassen Sie mich ein Beispiel geben, wo eine Verpackung erforderlich ist:
Stellen Sie sich einen Mikrocontroller vor, der mit einem EEPROM verbunden ist, in dem eine Struktur gespeichert wird.
Stellen Sie sich vor, eine Funktion, die in das EEPROM schreibt, würde wie folgt aussehen:
Wenn nun das Packen nicht durchgeführt wird, würden die zusätzlichen aufgefüllten Bytes Platz im EEPROM belegen, was keinen Nutzen hat.
@laurenz albe Danke, dass du meine Antwort präsentabler gemacht hast.
– Babajan
28. April 2019 um 18:31 Uhr
_attribute__((__packed__)) bedeutet (höchstwahrscheinlich) “keine Auffüllung einfügen, um die Dinge schneller zu machen” und kann auch bedeuten “keine Ausrichtungen einfügen, um die Ausrichtung beizubehalten”.
Eine Sache, die nicht ausdrücklich erwähnt wurde, ist, dass das Packen normalerweise so durchgeführt wird, dass es vordefinierten Feldstrukturen entspricht. Beispielsweise wird auf der unteren Ebene einer Netzwerkschnittstelle eine Reihe von Bytes zwischen vernetzten Maschinen ausgetauscht. Nachdem die Daten empfangen wurden, müssen sie einer übergeordneten Struktur zugeordnet werden, damit die Daten einfach bearbeitet werden können. In diesem Fall ist normalerweise kein Auffüllen erforderlich, sodass die Struktur direkt auf die Bytes abgebildet wird.
Der Netzwerkdatenaustausch beinhaltet auch ein Byte-Endianness-Problem (dh fast alle Netzwerkdaten verwenden das Big-Endian-Format, unabhängig von der Endianness der Quell- und Zielmaschinen).
Außerdem einige Maschinen kann nicht Greifen Sie auf breite Daten in nicht ausgerichteten Adressen zu, beispielsweise können Cortex-M0-Kerne nicht auf 32-Bit-Daten in nicht ausgerichteten 32-Bit-Adressen zugreifen, daher muss in solchen Fällen beim Schreiben von Netzwerkcode darauf geachtet werden.
13979300cookie-checkWas ist eine “gepackte” Struktur in C?yes