Frage

ich eine C # Hintergrund haben. Ich bin sehr viel ein Neuling auf eine Low-Level-Sprache wie C.

In C # Speicher der struct wird vom Compiler standardmäßig angelegt. Der Compiler kann erneut um Datenfelder oder Pad zusätzliche Bits zwischen den Feldern implizit. Also, ich hatte einiges spezielles Attribut festlegen, dieses Verhalten für genaues Layout außer Kraft zu setzen.

AFAIK, tut C nicht Neuordnungs oder align Speicherlayout eines struct standardmäßig. Allerdings habe ich gehört, es ist ein wenig Ausnahme, die sehr schwer zu finden ist.

Was ist C Speicher-Layout Verhalten? Was sollte neugeordneten / ausgerichtet sein und nicht?

War es hilfreich?

Lösung

In C wird der Compiler eine Ausrichtung für jeden primitiven Typen zu diktieren erlaubt. Typischerweise ist die Ausrichtung der Größe des Typs. Aber es ist völlig Umsetzung spezifisch.

Paddingbytes eingeführt werden, so wird jedes Objekt korrekt ausgerichtet. Neuordnen ist nicht erlaubt.

Möglicherweise jeder remote moderne Compiler implementiert #pragma pack, die Kontrolle über die Polsterung und überlässt es dem Programmierer mit dem ABI erfüllen können. (Es ist streng nicht dem Standard entsprechende, though.)

Von C99 §6.7.2.1:

12 Jedes Nicht-Bit-Feld Mitglied einer Objektstruktur oder Union ausgerichtet ist in einer implementierungs definiert entsprechend seiner Art.

13 Innerhalb eines Strukturobjekt, das nicht-Bitfeld Mitglieder, und die Einheiten, in denen Bit-Felder befinden Adressen haben, dass Erhöhung in der Reihenfolge, in der sie deklariert. Ein Zeiger auf eine Struktur, Objekt, in geeigneter Weise umgewandelt, weist auf sein Ausgangselement (oder wenn das Mitglied ist ein Bit-Feld an das Gerät, dann in der er sich befindet), und umgekehrt. Es kann in eine unbenannte Polsterung sein Strukturobjekt, aber nicht an seinem Anfang an.

Andere Tipps

Es ist implementierungsspezifisch, aber in der Praxis die Regel (in Abwesenheit von #pragma pack oder dergleichen) ist:

  • Struct Mitglieder werden in der Reihenfolge, wie sie deklariert sind, gespeichert. (Dies wird durch den C99-Standard erforderlich ist, wie hier bereits erwähnt).
  • Falls erforderlich, wird das Auffüllen vor jedem struct Mitglied hinzugefügt, eine korrekte Ausrichtung zu gewährleisten.
  • Jede primitive Typ T erfordert eine Ausrichtung von sizeof(T) Bytes.

So, da die folgende Struktur:

struct ST
{
   char ch1;
   short s;
   char ch2;
   long long ll;
   int i;
};
  • ch1 ist bei Offset 0
  • ein Füllbyte eingefügt auszurichten ...
  • s bei Offset 2
  • ch2 ist bei Offset 4, unmittelbar nach der s
  • 3 Füllbytes eingefügt auszurichten ...
  • ll bei Offset 8
  • i ist bei Offset 16, direkt nach ll
  • 4 Füllbytes werden am Ende hinzugefügt, so dass die Gesamt struct ein Vielfaches von 8 Bytes ist. Ich habe dies auf einem 64-Bit-System. 32-Bit-Systeme erlauben können structs 4-Byte-Ausrichtung haben

So sizeof(ST) ist 24.

Es kann bis zu 16 Byte reduziert werden, indem die Mitglieder zu vermeiden padding Umordnung:

struct ST
{
   long long ll; // @ 0
   int i;        // @ 8
   short s;      // @ 12
   char ch1;     // @ 14
   char ch2;     // @ 15
} ST;

Du kannst durch das Lesen der Datenstruktur Ausrichtung Wikipedia-Artikel besser erhalten Verständnis von Datenabgleich.

Von dem Wikipedia-Artikel :

Datenausrichtungseinrichtung, die Daten in einem Speicher setzen Offset gleich einem Vielfachen der Wortgröße, die die Leistung des Systems erhöht aufgrund der Art und Weise der CPU Griffe Speicher. Um die Daten auszurichten, kann es notwendig sein, einige bedeutungs Bytes zwischen dem Ende der letzten Datenstruktur und dem Anfang der nächsten einzufügen, die Datenstruktur padding ist.

6.54.8 Struktur-Verpackung Pragmas des GCC Dokumentation:

Für die Kompatibilität mit Microsoft Windows-Compiler unterstützt GCC einen Satz von Pragma-Richtlinien, die die Änderung maximale Ausrichtung von Mitgliedern Strukturen (ungleich Null-Breite bitfields), Gewerkschaften und Klassen anschließend definiert. Der n-Wert unten immer erforderlich ist ein klein sein Potenz von zwei und gibt den neuen Ausrichtung in Bytes.

  1. #pragma pack(n) setzt einfach die neue Ausrichtung.
  2. #pragma pack() legt die Ausrichtung auf die eine, die war in Effekt, wenn Kompilierung gestartet (siehe auch Zeilenoption Befehl -fpack-Struktur [=] siehe Code-Gen-Optionen).
  3. #pragma pack(push[,n]) schiebt die aktuelle Ausrichtung Einstellung auf eine interne Stapel und gegebenenfalls anschließend setzt die neue Ausrichtung.
  4. #pragma pack(pop) stellt die Ausrichtung Einstellung zu dem einen gespeicherten bei der obere Teil des inneren Stapels (und entfernt, den Stack-Eintrag). Beachten Sie, dass #pragma pack([n]) nicht über diesen internen Stapel beeinflussen; so ist es möglich #pragma pack(push) zu haben gefolgt von mehreren #pragma pack(n) Instanzen und durch einen einzigen abgeschlossen #pragma pack(pop).

Einige Ziele, z.B. i386 und powerpc, unterstützen die ms_struct #pragma welcher legt eine Struktur wie die dokumentiert out __attribute__ ((ms_struct)).

  1. #pragma ms_struct on abwechselnd auf das Layout für Strukturen erklärt.
  2. #pragma ms_struct off schaltet das Layout für Strukturen erklärt.
  3. #pragma ms_struct reset auf das Standard-Layout geht zurück.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top