2013-08-17 9 views
5

Ich habe eine Struktur wie folgt definiert:Warum ist offsetof (member) gleich groesse (struct)?

struct smth 
{ 
    char a; 
    int b[]; 
}; 

Als ich sizeof und offsetof auf diese Struktur nennen:

cout << sizeof(struct smth) << endl; 
cout << offsetof(struct smth, b) << endl; 

Ausgang ist:

4 
4 

Wie kommt es, wenn die Größe der stuct ist 4 und char verwendet 1 Byte, der Offset des int-Arrays ist 4? Warum gibt es eine Art Polsterung? Warum belegt das int-Array überhaupt keinen Platz?

+1

Sie meinen 'offsetof (struct smth, b)', oder? –

+0

@CarlNorum Ja, das tue ich. Bearbeitet. – bugra

+2

Ist es C oder C++? Sie sind anders. –

Antwort

8

Wie kommt es, wenn die Größe des Stuct ist 4 und Char verwendet 1 Byte, ist der Offset des Int-Array 4? Warum gibt es eine Art Polsterung?

Es gibt Padding, weil der C-Standard es erlaubt; Der Compiler richtet Variablen häufig aus, um die Leistung zu verbessern.

Auch, warum ist die zweite Variable überhaupt nicht besetzt (was wie der Fall scheint)?

Es ist ein C99 flexible Array-Mitglied - das ist der Kernpunkt. Die Idee ist, Ihre Struktur etwas wie zuzuordnen:

struct smth *s = malloc(sizeof *s + 10 * sizeof s->b[0]); 

Und dann würden Sie eine Struktur aufweisen, wie funktioniert, wenn b ein Array aus 10 Elementen waren.

+0

Welche Art von Leistungsverbesserungen erlaubt dies? Nur neugierig. – bugra

+0

@ biox6, einige Prozessoren Ladeanweisungen können nur Wörter von Wort-ausgerichteten Adressen laden. Wenn Sie ein Wort an einer nicht ausgerichteten Adresse haben, müssen Sie jedes Byte einzeln laden und neu kombinieren. –

+0

Ihre Zuweisungsanweisung berücksichtigt keine Ausrichtungsbeschränkungen. Im Allgemeinen wird es nicht möglich sein, die richtige Menge an Speicher zuzuweisen. Sie würden stattdessen eine richtig dimensionierte Struktur mit 'struct smth * s = malloc (offsetof (struct smth, b [10]));' zuweisen. – IInspectable

3

Da die Größe des Elements b Null ist, und der Compiler fügt Polsterung zwischen den a und b Mitgliedern so dass b auf einer „Wort“ Grenze ist.

Wenn ich jedoch erinnere, richtig zu haben, ein flexibles Array in einer Struktur wie das ist nur gültig C, nicht C++ außer als Compiler-Erweiterung.

+0

Hier ist das 'int b [] 'äquivalent zu int * b? – Light

+2

Nein, ist es nicht. 'int * b 'würde die' sizeof (smth) 'größer machen, und der zusätzliche Platz wäre dort, wo die Adresse einer int-Variablen gespeichert werden soll. Stattdessen sagt 'int b []', dass die Struktur dynamisch mit einer (zur Kompilierzeit unbekannten) Anzahl von ganzen Zahlen als ein einzelner Speicherblock zugewiesen werden soll. – mity

+0

@mity Wie weisen Sie der Variablen 'b' Werte zu? Könnten Sie mir die Zuweisungsanweisung geben? – Light

2

Da OP bemerkt, dass die Frage, C++ ist: wie b[]

struct smth 
{ 
    char a; 
    int b[]; 
}; 

Ein Array ist ungültig in C++. Das Array muss eine feste Größe haben. Arrays variabler Länge sind nur in C99 gültig.

Angenommen, Ihr Compiler unterstützt es als Erweiterung, das Array b[] hat eine Größe von Null, die die Struktur nur ein char Mitglied enthält. Die Padding-Regel in struct funktioniert, padding die struct zu einem Wort, das 4 Bytes in Ihrem Computer ist.