← SEARCHABLE ARCHIVE
Computer Science · 2026-05-13

Was ist Gedächtnisausrichtung?

Warum ist die Speichergröße unterschiedlich, obwohl es sich um die gleiche Struktur handelt?

INTERACTIVE READING MODE →

Die in diesem Blog verfassten Artikel wurden mit dem Ziel erstellt, zu unterrichten. Außerdem können die Informationen im Artikel falsch sein, also seien Sie bitte vorsichtig.

Beim Codieren kann es vorkommen, dass die Größe der Struktur von meinen Erwartungen abweicht. Dieses Phänomen wird offiziell Memory Alignment and Padding genannt.

Wenn die CPU Variablen aus dem Speicher liest, liest sie diese nicht in Einheiten von 1 Byte. Da es in Blöcken Wort für Wort gelesen wird (normalerweise 4 Bytes oder 8 Bytes), ist die Anordnung der Variablen im Speicher für die Leistung äußerst wichtig.

Die Gesamtgröße der Struktur kann abhängig von der Anordnung der Strukturelemente im Speicher variieren. Dies ist auf das Konzept der Polsterung zurückzuführen. Beim Padding handelt es sich um leeren Raum, den der Compiler automatisch einfügt, um die Elemente einer Struktur an Wortgrenzen auf der CPU auszurichten. Da in der Mitte ein leerer Raum vorhanden ist, nimmt die Größe der Struktur natürlich zu.

Lassen Sie es uns selbst anhand des Codes überprüfen.

#include <iostream>
#include <cstddef> //Verwenden des Offsetof-Makros

//1. Ineffiziente Speicherplatzierung (insgesamt 24 Bytes)
struct BadOrder {
    int A;       //4 Bytes, die nächste Variable erfordert eine 8-Byte-Ausrichtung, was zu 4 Bytes Auffüllung führt (insgesamt 8 Bytes).
    long long B; //8 Bytes, 8 Bytes allein verwendet. (Insgesamt 16 Bytes verwendet)
    bool C;      //1 Byte, 7 Bytes werden aufgefüllt, nachdem 1 Byte verwendet wurde (insgesamt werden 24 Bytes verwendet).
};

//2. Effiziente Speicherplatzierung unter Berücksichtigung der Compiler-Optimierung (insgesamt 16 Bytes)
struct GoodOrder {
    long long A; //8 Bytes, 8 Bytes allein verwendet. (Insgesamt 8 Bytes verwendet)
    int B;       //4 Bytes, die folgenden Variablen können in den verbleibenden 4 Bytes verwendet werden, sodass kein Auffüllen erfolgt. (Insgesamt 12 Bytes verwendet)
    bool C;      //1 Byte, 3 Bytes Auffüllen erfolgt, nachdem 1 Byte verwendet wurde. (Insgesamt 16 Bytes verwendet)
};

//3. Struktur mit zwangsweise entferntem Padding (insgesamt 13 Bytes)
#pragma pack(push, 1)
struct PackedStruct {
    int A;       // 4 Byte
    long long B; // 8 Byte
    bool C;      // 1 Byte
};
#pragma pack(pop)

Hier stellt sich eine Frage. Warum gibt es am Ende von BadOrder zusätzlich 7 Bytes Auffüllung und am Ende von GoodOrder 3 Bytes Auffüllung? Dies ist auf Ausrichtungsanforderungen zurückzuführen, wenn Strukturen in Arrays usw. gruppiert werden. Die Gesamtgröße der Struktur muss ein Vielfaches des größten Datentyps (im Beispiel oben 8 Byte long long) unter den internen Mitgliedern sein. Dies liegt daran, dass beim Übergang zum nächsten Element des Arrays die gleiche 8-Byte-Ausrichtung garantiert werden kann.

Nummer 3 besteht darin, die Polsterung mithilfe von #pragma pack gewaltsam zu entfernen. Dadurch kann der Speicher auf nur 13 Byte eingespart werden, es kann jedoch zu schwerwiegenden Leistungseinbußen führen. Wenn die CPU Wort für Wort liest und der Startpunkt der Daten falsch ausgerichtet ist, Die CPU muss den Speicher zweimal lesen und eine nutzlose zusätzliche Operation ausführen, um die Zusammenführung zu erzwingen. In bestimmten Hardwareumgebungen kann es sogar zum Absturz des Programms kommen.

Darüber hinaus kann die Effizienz der Cache-Zeile nicht ignoriert werden. Moderne CPUs importieren den gesamten Speicher meist in Einheiten von 64 Byte, wenn es aber wie bei Nummer 1 24 Byte sind, können in 64 Byte nur 2 gespeichert werden. Wenn Sie es wie in Nummer 2 auf 16 Bytes optimieren, passen alle 4 genau hinein. Beim Schleifen eines Arrays gibt es einen großen Unterschied in der Verarbeitungsgeschwindigkeit.

Sofern es keine Sonderfälle gibt, in denen das Speicherlayout ohne 1-Byte-Fehler genau sein muss, wie z. B. Netzwerkkommunikationsstandards oder Dateieingabe/-ausgabe, Im Allgemeinen hat das Zulassen von Polsterung größere Leistungsvorteile. Deshalb ist es eine gute Idee, sich angewöhnen, unnötiges Auffüllen zu minimieren, indem man die Mitglieder beginnend mit der größten Größe (oder in umgekehrter Reihenfolge) gruppiert, wie in Nummer 2 gezeigt.