867 Stimmen

Warum ist sizeof für eine Struktur nicht gleich der Summe von sizeof der einzelnen Mitglieder?

Warum ist die sizeof Operator für eine Struktur eine Größe zurück, die größer ist als die Gesamtgröße der Mitglieder der Struktur?

20 Stimmen

Siehe diese C-FAQ zur Speicherverwaltung. c-faq.com/struct/align.esr.html

71 Stimmen

Eine Anekdote: Es gab tatsächlich einen Computervirus, der seinen Code in Struktur-Paddings im Wirtsprogramm unterbrachte.

10 Stimmen

@Elazar Das ist beeindruckend! Ich hätte es nie für möglich gehalten, so winzige Flächen für irgendetwas zu nutzen. Können Sie weitere Einzelheiten nennen?

798voto

Kevin Punkte 24023

Dies liegt an der Auffüllung, die hinzugefügt wurde, um die Ausrichtungsvorgaben zu erfüllen. Abgleich der Datenstruktur wirkt sich sowohl auf die Leistung als auch auf die Korrektheit von Programmen aus:

  • Ein falsch ausgerichteter Zugriff kann ein schwerer Fehler sein (oft SIGBUS ).
  • Ein falsch ausgerichteter Zugriff kann ein weicher Fehler sein.
    • Entweder in der Hardware korrigiert, für eine bescheidene Leistungsverschlechterung.
    • Oder durch Emulation in Software korrigiert werden, um eine starke Leistungsverschlechterung zu vermeiden.
    • Darüber hinaus können Atomarität und andere Gleichzeitigkeitsgarantien gebrochen werden, was zu subtilen Fehlern führt.

Hier ist ein Beispiel mit typischen Einstellungen für einen x86-Prozessor (alle verwendeten 32- und 64-Bit-Modi):

struct X
{
    short s; /* 2 bytes */
             /* 2 padding bytes */
    int   i; /* 4 bytes */
    char  c; /* 1 byte */
             /* 3 padding bytes */
};

struct Y
{
    int   i; /* 4 bytes */
    char  c; /* 1 byte */
             /* 1 padding byte */
    short s; /* 2 bytes */
};

struct Z
{
    int   i; /* 4 bytes */
    short s; /* 2 bytes */
    char  c; /* 1 byte */
             /* 1 padding byte */
};

const int sizeX = sizeof(struct X); /* = 12 */
const int sizeY = sizeof(struct Y); /* = 8 */
const int sizeZ = sizeof(struct Z); /* = 8 */

Man kann die Größe von Strukturen minimieren, indem man die Mitglieder nach der Ausrichtung sortiert (bei Basistypen reicht die Sortierung nach der Größe aus) (z. B. Struktur Z im obigen Beispiel).

WICHTIGER HINWEIS: Sowohl der C- als auch der C++-Standard besagen, dass die Strukturausrichtung implementierungsabhängig ist. Daher kann jeder Compiler die Daten anders ausrichten, was zu unterschiedlichen und inkompatiblen Datenlayouts führt. Aus diesem Grund ist es beim Umgang mit Bibliotheken, die von verschiedenen Compilern verwendet werden, wichtig zu verstehen, wie die Compiler die Daten ausrichten. Einige Compiler haben Kommandozeileneinstellungen und/oder spezielle #pragma Anweisungen, um die Einstellungen für die Strukturausrichtung zu ändern.

261voto

EmmEff Punkte 7393

Packen und Byte-Ausrichtung, wie in den C-FAQ beschrieben ici :

Es geht um die Ausrichtung. Viele Prozessoren können nicht auf 2- und 4-Byte Mengen (z.B. ints und long ints) zugreifen, wenn sie in alle Richtungen eingepfercht sind. in alle Richtungen.

Angenommen, Sie haben diese Struktur:

struct {
    char a[3];
    short int b;
    long int c;
    char d[3];
};

N Struktur auf diese Weise in den Speicher zu packen:

+-------+-------+-------+-------+
|           a           |   b   |
+-------+-------+-------+-------+
|   b   |           c           |
+-------+-------+-------+-------+
|   c   |           d           |
+-------+-------+-------+-------+

B es so anordnet:

+-------+-------+-------+
|           a           |
+-------+-------+-------+
|       b       |
+-------+-------+-------+-------+
|               c               |
+-------+-------+-------+-------+
|           d           |
+-------+-------+-------+

I Sie und ich sehen, wie sich die Felder b und c umdrehen? Kurz und bündig, es ist auch für den Prozessor schwierig. Daher polstern die meisten Compiler die Struktur (wie mit zusätzlichen, unsichtbaren Feldern) wie folgt auf:

+-------+-------+-------+-------+
|           a           | pad1  |
+-------+-------+-------+-------+
|       b       |     pad2      |
+-------+-------+-------+-------+
|               c               |
+-------+-------+-------+-------+
|           d           | pad3  |
+-------+-------+-------+-------+

35voto

INS Punkte 10083

Wenn Sie wollen, dass die Struktur eine bestimmte Größe hat, verwenden Sie zum Beispiel mit GCC __attribute__((packed)) .

Unter Windows können Sie die Ausrichtung auf ein Byte setzen, wenn Sie das Programm cl.exe mit dem Befehl Option /Zp .

Normalerweise ist es für die CPU einfacher, auf Daten zuzugreifen, die ein Vielfaches von 4 (oder 8) sind, je nach Plattform und auch je nach Compiler.

Es ist also im Grunde eine Frage der Ausrichtung.

Sie müssen gute Gründe haben, sie zu ändern.

19voto

Kyle Burton Punkte 25900

Dies kann auf die Ausrichtung der Bytes und das Auffüllen zurückzuführen sein, damit die Struktur auf Ihrer Plattform eine gerade Anzahl von Bytes (oder Wörtern) ergibt. Zum Beispiel in C auf Linux, die folgenden 3 Strukturen:

#include "stdio.h"

struct oneInt {
  int x;
};

struct twoInts {
  int x;
  int y;
};

struct someBits {
  int x:2;
  int y:6;
};

int main (int argc, char** argv) {
  printf("oneInt=%zu\n",sizeof(struct oneInt));
  printf("twoInts=%zu\n",sizeof(struct twoInts));
  printf("someBits=%zu\n",sizeof(struct someBits));
  return 0;
}

haben Mitglieder, deren Größe (in Bytes) jeweils 4 Bytes (32 Bits), 8 Bytes (2x 32 Bits) und 1 Byte (2+6 Bits) beträgt. Das obige Programm (unter Linux mit gcc) gibt die Größen als 4, 8 und 4 aus - wobei die letzte Struktur so aufgefüllt wird, dass sie ein einzelnes Wort ist (4 x 8 Bit-Bytes auf meiner 32-Bit-Plattform).

oneInt=4
twoInts=8
someBits=4

13voto

lkanab Punkte 886

Siehe auch:

für Microsoft Visual C:

http://msdn.microsoft.com/en-us/library/2e70t5y1%28v=vs.80%29.aspx

und GCC behaupten Kompatibilität mit Microsofts Compiler..:

https://gcc.gnu.org/onlinedocs/gcc-4.6.4/gcc/Structure_002dPacking-Pragmas.html

Zusätzlich zu den vorangegangenen Antworten, beachten Sie bitte, dass unabhängig von der Verpackung, in C++ gibt es keine "members-order-guarantee . Compiler können der Struktur Zeiger auf virtuelle Tabellen und Mitglieder von Basisstrukturen hinzufügen (und tun dies sicherlich auch). Selbst das Vorhandensein einer virtuellen Tabelle wird von der Norm nicht garantiert (die Implementierung des virtuellen Mechanismus ist nicht spezifiziert), so dass man zu dem Schluss kommen kann, dass eine solche Garantie einfach unmöglich ist.

Ich bin mir ziemlich sicher, dass Mitglied-Bestellung garantiert in C aber ich würde mich nicht darauf verlassen, wenn ich ein plattform- oder kompilerübergreifendes Programm schreibe.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X