2010-04-17 10 views
13

Ich weiß, dass ein char und ein Int als 8 Bytes auf 32-Bit-Architekturen aufgrund der Ausrichtung berechnet werden, aber ich stieß kürzlich auf eine Situation, in der eine Struktur mit 3 Kurzschlüssen gemeldet wurde 6 Bytes von der Größe des Operators. Code ist wie folgt:Wie wird Größe berechnet die Größe von Strukturen

#include <iostream> 
using namespace std ; 

struct IntAndChar 
{ 
    int a ; 
    unsigned char b ; 
}; 


struct ThreeShorts 
{ 
    unsigned short a ; 
    unsigned short b ; 
    unsigned short c ; 
}; 


int main() 
{ 
    cout<<sizeof(IntAndChar)<<endl; // outputs '8' 
    cout<<sizeof(ThreeShorts)<<endl; // outputs '6', I expected this to be '8' 
    return 0 ; 
} 

Compiler: g ++ (Debian 4.3.2-1.1) 4.3.2. Das verwirrt mich wirklich, warum wird Ausrichtung für die Struktur nicht durchgesetzt, die 3 Kurzschlüsse enthält?

Antwort

21

Das liegt daran, int ist 4 Bytes und muss an einer 4-Byte-Grenze ausgerichtet werden. Das bedeutet, dass ANY struct mit einem int auch auf mindestens 4 Bytes ausgerichtet werden muss.

Auf der anderen Seite ist short 2 Bytes, und Ausrichtung nur an einer 2-Byte-Grenze benötigt.Wenn ein struct, der short enthält, nichts enthält, das eine größere Ausrichtung benötigt, wird struct auch auf 2 Bytes ausgerichtet.

2

Es ist völlig abhängig von der Implementierung, aber vermutlich, wenn Ihr System eine der drei short s in der Struktur, ohne sich Gedanken über die Ausrichtung zugreifen kann, kann es jede short zugreifen und so alle Daten, Mitglied in einer Reihe von ThreeShorts ohne Sorgen um Ausrichtung. Daher müssen die Strukturen nicht strikter ausgerichtet werden.

Für das IntAndChar Beispiel int hat vermutlich die Größe 4 und die Umsetzung mit seiner Ausrichtung betrifft. Um sicherzustellen, dass alle int Mitglied in einem Array von IntAndChar richtig ausgerichtet ist, muss die Struktur aufgefüllt werden.

Die sizeof ein Array T[n] ist genau definiert als sizeof(T) * n.

15

Das verwirrt mich wirklich, warum für die Ausrichtung nicht t erzwungen

Welche Ausrichtung haben Sie es haben wollen?

Kurzschlüsse können auf 2-Byte-Grenzen ohne negative Auswirkungen ausgerichtet werden (vorausgesetzt, gemeinsame X86-Compiler sind hier überall ..). Wenn Sie also ein Array von struct ThreeeShorts erstellen, ist diese Struktur mit einer Größe von 6 in Ordnung, da alle Elemente in einem solchen Array auf einer 2-Byte-Grenze beginnen.

Ihre struct IntAndChar enthält ein int, ints will 4-Byte-Ausrichtung, also, wenn Sie ein Array von struct IntAndChar erstellen müssen die Größe 8 für das nächste Element an einer 4-Byte-Grenze ausgerichtet werden.

Wenn wir Arrays nicht in Betracht ziehen, würde es nicht viel ausmachen, wenn struct IntAndChar 5 Bytes lang wären, würde der Compiler es nur auf einer 4-Byte-Grenze zuweisen, wenn Sie einen der Stapel erstellen oder als einen verwenden Verbundelement in einer anderen Struktur.

Sie können die Anzahl der Elemente in einem Array immer mit sizeof (arrayofT)/sizeof (T) ermitteln, und Arrayelemente werden garantiert nebeneinander gespeichert, sodass das n-te Element durch schrittweises N retriviert werden kann * sizeof (Arrayelementtype) Bytes von Anfang an, und das ist der Hauptgrund, warum Strukturen am Ende aufgefüllt werden.

+0

Es ist nicht, dass ich eine bestimmte Ausrichtung möchte, es ist nur, dass ich, dass die 4-Byte-Ausrichtung immer auf 32-Bit-Architekturen eingehalten wurde –

+0

Wenn nur! Es würde sicherlich viel einfacher machen, Speicherzuweiser zu schreiben ...Leider kann sich die Ausrichtung von einem Typ zum anderen unterscheiden, und es gibt keinen portablen Weg, den Compiler nach der bestimmten Ausrichtung eines bestimmten Typs zu fragen, obwohl es Tricks gibt. –

+0

'#define alignof (type) ((char *) & ((struct {char dummy; typ x;} *) 0) -> x - (char *) 0)' –

6

Ich weiß nicht, wo Sie die Idee über char oder int als "8 Bytes" berechnet bekommen. Nein, jeder Typ wird entsprechend seiner Größe berechnet: char als 1, int als 4 auf einer 32-Bit-Plattform (nicht 8, sondern 4). Die Ausrichtungsanforderung für jeden Typ ist normalerweise die gleiche wie seine Größe (obwohl dies nicht notwendig ist).

Aus diesem Grund, wenn die Struktur der Mitglieder des gleichen Typ enthält, wird in der Regel die Gesamtgröße dieser Struktur die genaue Summe der Größen ihrer Mitglieder sein: eine Struktur von 3 char s wird 3 haben eine Größe und die Struktur von zwei int s wird Größe 8 haben.

Offenbar Typ short auf Ihrer Plattform hat Größe 2, so erwartet, eine Struktur von 3 Shorts hat Größe 6, die genau das ist, was Sie beobachten.

Wenn Ihre Struktur jedoch Mitglieder verschiedene Typen enthält, kommt der Unterschied zwischen Ausrichtungsanforderungen verschiedener Typen ins Spiel. Wenn die Ausrichtungsanforderung des nächsten Felds strenger ist als die Ausrichtungsanforderung des vorherigen Felds, muss der Compiler zwischen diesen Feldern möglicherweise einige Füllbytes hinzufügen (um das nächste Element richtig auszurichten), was sich auf die endgültige Größe der Struktur auswirkt. Außerdem muss der Compiler nach dem letzten Element der Struktur möglicherweise einige zusätzliche Füllbytes hinzufügen, um die Ausrichtungsanforderungen in einem Array zu erfüllen.

Zum Beispiel einer Struktur, die

struct S { 
    char c; 
    int i; 
}; 

wird höchstwahrscheinlich besetzen 8 Bytes auf Ihrer Plattform wegen der Notwendigkeit, für 3 Paddingbytes nach dem char Mitglied wie folgt aussieht. Man beachte, char zählt als 1, int als 4 und die zusätzlichen 3 Füllbytes zwischen ihnen machen es 8.

beachte auch, dass dies leicht die Abhängigkeit der endgültigen Größe der Struktur in der Größenordnung einführen könnte, in denen die Mitglieder erklärt. Zum Beispiel diese Struktur

struct S1 { 
    char c1; 
    int i; 
    char c2; 
}; 

auf Ihrer Plattform wird wahrscheinlich Größe 12, während diese ein

struct S2 { 
    int i; 
    char c1; 
    char c2; 
}; 

nur 8 Bytes besetzen. Dieses letzte Beispiel soll veranschaulichen, dass die endgültige Größe der Struktur nicht ausgedrückt werden kann in Bezug darauf, wie viele Bytes jedes Mitglied "zählt". Die Beziehungen zwischen den Mitgliedern sind ebenfalls wichtig.

1

Ja, ich hatte das gleiche Problem. Ich habe die folgende Struktur

struct Node{ 
    short digit; 
    Node* next; 
}; 
    cout<<":"<<sizeof(Node)<<":"<<sizeof(short)<<":"<<sizeof(Node*)<<endl; 

Das gibt mir :: 8: 2: 4 ?? Warum ist die Gesamtsumme für die Struktur = 8, aber einzelne Elemente summieren sich nicht ?? Dies ist wegen der Speicherausrichtung, der Speicher ist mit zusätzlichen 2 Bytes für die Ausrichtung aufgefüllt. Danke