Unterschied zwischen einer Struktur und einem Verband

Gibt es ein gutes Beispiel, um den Unterschied zwischen einem "Konstrukt" und einer "Vereinigung" zu erklären? Grundsätzlich weiß ich, dass struct den gesamten Speicher seines Mitglieds nutzt und union den Speicherplatz des größten Mitglieds. Gibt es noch andere Unterschiede auf Betriebssystemebene?

Lösung

Bei einer Union braucht man nur eines der Elemente zu verwenden, da sie alle an der gleichen Stelle gespeichert sind. Dies ist nützlich, wenn Sie etwas speichern wollen, das von mehreren Typen sein könnte. Eine Struktur hingegen hat für jedes ihrer Elemente einen eigenen Speicherplatz, und sie können alle gleichzeitig verwendet werden.

Um ein konkretes Beispiel für ihre Verwendung zu geben, habe ich vor einiger Zeit an einem Scheme-Interpreter gearbeitet und dabei im Wesentlichen die Scheme-Datentypen über die C-Datentypen gelegt. Dazu musste ich in einer Struktur ein Enum speichern, das den Typ des Wertes angibt, und eine Union, die diesen Wert speichert.

union foo {
  int a;   // can't use both a and b at once
  char b;
} foo;

struct bar {
  int a;   // can use both a and b simultaneously
  char b;
} bar;

union foo x;
x.a = 3; // OK
x.b = 'c'; // NO! this affects the value of x.a!

struct bar y;
y.a = 3; // OK
y.b = 'c'; // OK

edit: Wenn Sie sich fragen, was die Einstellung von x.b auf 'c' den Wert von x.a ändert, so ist dies technisch gesehen undefiniert. Auf den meisten modernen Rechnern ist ein char 1 Byte und ein int 4 Byte groß. Wenn Sie also x.b den Wert 'c' geben, erhält auch das erste Byte von x.a den gleichen Wert:

union foo x;
x.a = 3;
x.b = 'c';
printf("%i, %i\n", x.a, x.b);

druckt

99, 99

Warum sind die beiden Werte identisch? Weil die letzten 3 Bytes von int 3 alle Nullen sind, so dass es auch als 99 gelesen wird. Wenn wir eine größere Zahl für x.a eingeben, werden Sie sehen, dass dies nicht immer der Fall ist:

union foo x;
x.a = 387439;
x.b = 'c';
printf("%i, %i\n", x.a, x.b);

druckt

387427, 99

Um einen genaueren Blick auf die tatsächlichen Speicherwerte zu werfen, lassen Sie uns die Werte in hexadezimaler Form setzen und ausdrucken:

union foo x;
x.a = 0xDEADBEEF;
x.b = 0x22;
printf("%x, %x\n", x.a, x.b);

druckt

deadbe22, 22

Sie können deutlich sehen, wo die 0x22 die 0xEF überschrieben hat.

ABER

In C ist die Reihenfolge der Bytes in einem int nicht definiert. Dieses Programm hat auf meinem Mac das 0xEF mit 0x22 überschrieben, aber auf anderen Plattformen würde es stattdessen das 0xDE überschreiben, weil die Reihenfolge der Bytes, aus denen der int besteht, vertauscht ist. Wenn Sie ein Programm schreiben, sollten Sie sich daher nie auf das Verhalten des Überschreibens bestimmter Daten in einer Union verlassen, da es nicht portabel ist.

Weitere Informationen über die Reihenfolge von Bytes finden Sie unter endianness.

Kommentare (12)

"union" und "struct" sind Konstrukte der Sprache C. Es ist unangemessen, von einem Unterschied auf Betriebssystemebene zu sprechen, da es der Compiler ist, der unterschiedlichen Code erzeugt, wenn Sie das eine oder andere Schlüsselwort verwenden.

Kommentare (0)

Eine Struktur weist die Gesamtgröße aller Elemente in ihr zu.

Eine Union weist nur so viel Speicher zu, wie ihr größtes Mitglied benötigt.

Kommentare (1)