Größe von Struktur anders mit sizeof()?

Hi,
Ich habe folgende Struktur definiert:

struct Name{
int Zahl;
char wort[50];
char *Zeiger;
}n;

Bei einem 32-Bit System besteht doch die Struktur aus 58 Bytes (int Zahl 4 Bytes, char wort[50] 50 Bytes, char *Zeiger 4 Bytes;
4+50+4 = 58). Wenn ich nun aber die Größe mit sizeof() ermittele, dann gibt mir mein Computer 60 Bytes zurück. Woher kommen die 2 zusätzlichen Bytes? Ich habe gehört, dass das mit Optimierungsgründen zusammenhängt. Wenn ja, was bedeutet das genau?

Danke im Voraus!

kommen die 2 zusätzlichen Bytes? Ich habe gehört, dass das mit
Optimierungsgründen zusammenhängt. Wenn ja, was bedeutet das
genau?

Ja in gewissermassen, damit der zugriff auf die einzelnen member von einer structur möglichst schnell geht, erzeugt der Compiler sogenannte padding (also zwischenräume) . Das garantiert auch kompailibilät.
Mann kann es abschalten das es ohne lücken gemacht wird, ist allerdings langsam und nciht kompatibel mit so einigem :smile:

Hab nur was in englisch gefunden das das erklärt.

To produce faster code, GCC pads struct members so that each one can be accessed without delays; this sometimes produces struct size which is larger than the sum of the sizes of its members. If you need to minimize this padding (e.g., if your program uses large arrays of such structs, where padding will waste a lot of memory), lay out your structures so that the longer members are before the shorter ones. For example, let's say that you have a struct defined thus:

 struct my\_struct {
 char name[7];
 unsigned long offset;
 double quality;
 };

To make such a struct use the least number of bytes, rearrange the members, like this40:

 struct my\_struct {
 double quality;
 unsigned long offset;
 char name[7];
 };

If the layout of the structure cannot be changed (e.g., when it must match some external specification, like a block of data returned by a system call), you can use the \_\_attribute\_\_((packed)) extension of GCC (see GNU C/C++ Manual.) to prevent GCC from padding the structure members; this will make accesses to some of the members significantly slower.

Beginning with version 2.7.0, GCC has a command-line option -fpack-struct which causes GCC to pack all members of all structs together without any holes, just as if you used \_\_attribute\_\_((packed)) on every struct declaration in the source file you compile with that switch. If you use this switch, be sure that source files which you compile with it don't use any of the structures defined by library functions, or you will get some members garbled (because the library functions weren't compiled with that switch). Also, GCC 2.95.1 and 2.95.2 had bugs in their support of -fpack-struct (the bug is corrected in v2.96 and later). 

Hallo,

zur Zugriffsoptimierung richtet der Compiler die einzelnen Datenfelder nach Wort- (16bit) oder Doppelwort (32bit) Grenzen aus, im vorliegenden Fall offenbar auf 4 Byte: 50 Byte sind aber nicht durch 4 teilbar, also wird das letzte Feld um 2 Byte verschoben. Gesamt int Zahl 4 Bytes, char wort[50] 50 Bytes, 2 Bytes „Padding“, char *Zeiger 4 Bytes.

Es kann sein, dass ein 64bit-Compiler sogar auf 8 Byte-Grenzen ausrichtet.

Kann man das nicht akzepieren, z.B, weil die Struktur extern vorgegeben ist, so gibt es in Pascal die definition „packed record“ anstatt „record“, in C/C++ gibt es Compileranweisungen dazu, die müsste man auch unter dem Stichwort „packed“ finden.

Gruss Reinhard

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Morgen!

Ich habe gehört, dass das mit Optimierungsgründen zusammenhängt

Auch aber nicht nur.

Wenn du dir ein 32Bit System vorstellst, dann befinden sich auf
Wortadresse 0 die Bytes 0-3, auf Wortadresse 1 die Bytes 4-7 usw.

In deinem Beispiel wäre der 4 Byte große Zeiger in den Bytes 55, 56, 57
und 58. Dies entspricht den Wortadressen 13 & 14, heißt die CPU
muß zweimal in den Speicher greifen um den Zeiger zu lesen. Das
nennt man dann auch „miss aligned“.

Eine Intel CPU (x86) macht das sogar, ein ARM, PowerPC etc würde
sich aufs Maul legen und eine Exeption erzeugen (so wie Division
durch 0).

Lange Rede kurzer Sinn, ein Compiler wird mindestens jedes
Structurmember auf die natürlich Speicherbreite ausrichten.

Falls der Compiler dann die Ausführungsgeschwindigkeit optimieren
will können auch noch gröbere Ausrichtungen genutzt werden
(z.B. Cache line Größe).

Mit Mikkisoft kannst du das Compiler alignment ändern mit
#pragma pack( x )

Gruß
Stefan

Hallo Fragewurm,

Als Grund wurde ja das Aligmnet schon beschrieben.

struct Name{
int Zahl;
char wort[50];
char *Zeiger;
}n;

Wenn du die Möglichkeit hast, kannst du auch die Reihenfolge der Struktur ändern.

Zeiger und ints haben normalerweise diejenige Grösse, welche die CPU mit einem oder zwei Zugriffen einlesen kann. Also kann man diese an den Anfang stellen. Auf char wird 8- oder 16-bitweise (Unicode) zugegriffen und sollten deshalb am Ende der Struktur stehen, wenn man auf eine optimale Speicherausnutzung Wert legt.

MfG Peter(TOO)