Bei einer Union sollten Sie nur eines der Elemente verwenden, da sie alle an derselben Stelle gespeichert sind. Dies ist nützlich, wenn Sie etwas speichern möchten, das einer von mehreren Typen sein kann. Eine Struktur hat andererseits einen separaten Speicherort für jedes ihrer Elemente 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 Schema-Interpreter gearbeitet und die Schema-Datentypen im Wesentlichen auf die C-Datentypen gelegt. Dies beinhaltete das Speichern einer Aufzählung in einer Struktur, die den Werttyp angibt, und einer Vereinigung zum Speichern dieses Werts.
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
Bearbeiten: Wenn Sie sich fragen, durch welche Einstellung von xb auf 'c' der Wert von xa geändert wird, ist er technisch gesehen undefiniert. Auf den meisten modernen Maschinen ist ein Zeichen 1 Byte und ein Int 4 Byte. Wenn Sie also xb den Wert 'c' geben, erhält auch das erste Byte von xa denselben 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 gleich? Da die letzten 3 Bytes von int 3 alle Null sind, wird es auch als 99 gelesen. Wenn wir für xa eine größere Zahl eingeben, werden Sie feststellen, 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 die tatsächlichen Speicherwerte genauer zu betrachten, setzen wir die Werte in hexadezimaler Form und drucken sie aus:
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 der 0x22 den 0xEF überschrieben hat.
ABER
In C ist die Reihenfolge der Bytes in einem int nicht definiert. Dieses Programm hat die 0xEF mit 0x22 auf meinem Mac überschrieben, aber es gibt andere Plattformen, auf denen es stattdessen die 0xDE überschreibt, da die Reihenfolge der Bytes, aus denen die int besteht, umgekehrt wurde. Daher sollten Sie sich beim Schreiben eines Programms niemals auf das Verhalten beim Überschreiben bestimmter Daten in einer Union verlassen, da diese nicht portierbar sind.
Weitere Informationen zur Reihenfolge der Bytes finden Sie unter endianness .
Hier ist die kurze Antwort: Eine Struktur ist eine Datensatzstruktur: Jedes Element in der Struktur weist neuen Speicherplatz zu. Also eine Struktur wie
weist
(sizeof(int)+sizeof(long)+sizeof(double)+sizeof(long double))
jeder Instanz mindestens Bytes im Speicher zu. ("Zumindest", da Einschränkungen bei der Architekturausrichtung den Compiler zwingen können, die Struktur aufzufüllen.)Auf der anderen Seite,
weist einen Teil des Speichers zu und gibt ihm vier Aliase. Also
sizeof(union foobarbazquux_u) ≥ max((sizeof(int),sizeof(long),sizeof(double),sizeof(long double))
wieder mit der Möglichkeit einer Hinzufügung für Ausrichtungen.quelle
Ein imaginäres Kommunikationsprotokoll
In diesem imaginären Protokoll wurde spezifiziert, dass basierend auf dem "Nachrichtentyp" die folgende Position im Header entweder eine Anforderungsnummer oder ein vierstelliger Code ist, aber nicht beide. Kurz gesagt, Gewerkschaften erlauben, dass derselbe Speicherort mehr als einen Datentyp darstellt, wobei garantiert ist, dass Sie immer nur einen der Datentypen gleichzeitig speichern möchten.
Gewerkschaften sind größtenteils ein Detail auf niedriger Ebene, das auf dem Erbe von C als Systemprogrammiersprache basiert, wobei manchmal "überlappende" Speicherorte auf diese Weise verwendet werden. Sie können manchmal Gewerkschaften verwenden, um Speicher zu speichern, wenn Sie eine Datenstruktur haben, in der nur einer von mehreren Typen gleichzeitig gespeichert wird.
Im Allgemeinen kümmert sich das Betriebssystem nicht um Strukturen und Gewerkschaften - beide sind einfach Speicherblöcke. Eine Struktur ist ein Speicherblock, in dem mehrere Datenobjekte gespeichert sind, wobei sich diese Objekte nicht überlappen. Eine Union ist ein Speicherblock, in dem mehrere Datenobjekte gespeichert sind, für den jedoch nur das größte gespeichert ist. Daher kann jeweils nur eines der Datenobjekte gespeichert werden.
quelle
packetheader ph;
Wie greifen Sie auf die Anforderungsnummer zu?ph.request.requestnumber
?Wie Sie bereits in Ihrer Frage festgestellt haben, besteht der Hauptunterschied zwischen
union
undstruct
darin, dassunion
Mitglieder den Speicher voneinander überlagern, sodass die Größe einer Gewerkschaft diejenige ist, während diestruct
Mitglieder nacheinander angeordnet werden (mit optionaler Auffüllung dazwischen). Außerdem ist eine Gewerkschaft groß genug, um alle ihre Mitglieder aufzunehmen und eine Ausrichtung zu haben, die allen ihren Mitgliedern entspricht. Nehmen wir also an, esint
kann nur an 2-Byte-Adressen gespeichert werden und ist 2 Byte breit, und long kann nur an 4-Byte-Adressen gespeichert werden und ist 4 Byte lang. Die folgende Vereinigungkönnte eine
sizeof
von 4 und eine Ausrichtungsanforderung von 4 haben. Sowohl eine Vereinigung als auch eine Struktur können am Ende, aber nicht am Anfang, eine Auffüllung haben. Das Schreiben in eine Struktur ändert nur den Wert des Mitglieds, in das geschrieben wurde. Wenn Sie an ein Gewerkschaftsmitglied schreiben, wird der Wert aller anderen Mitglieder ungültig. Sie können nicht auf sie zugreifen, wenn Sie noch nicht darauf geschrieben haben. Andernfalls ist das Verhalten undefiniert. GCC bietet eine Erweiterung, die Sie tatsächlich von Gewerkschaftsmitgliedern lesen können, obwohl Sie ihnen zuletzt nicht geschrieben haben. Für ein Betriebssystem muss es keine Rolle spielen, ob ein Benutzerprogramm in eine Union oder in eine Struktur schreibt. Dies ist eigentlich nur ein Problem des Compilers.Eine weitere wichtige Eigenschaft von union und struct ist, dass ein Zeiger auf sie auf Typen eines ihrer Mitglieder verweisen kann . Folgendes gilt also:
some_test_pointer kann auf
int*
oder zeigendouble*
. Wenn Sie eine Adresse vom Typtest
inint*
umwandeln, verweist siea
tatsächlich auf das erste Mitglied . Gleiches gilt auch für eine Gewerkschaft. Da eine Union immer die richtige Ausrichtung hat, können Sie eine Union verwenden, um das Zeigen auf einen Typ gültig zu machen:Diese Vereinigung wird tatsächlich in der Lage sein, auf ein int und ein double zu verweisen:
ist tatsächlich gültig, wie im C99-Standard angegeben:
Der Compiler optimiert das nicht,
v->a = 10;
da es den Wert von beeinflussen könnte*some_int_pointer
(und die Funktion wird10
stattdessen zurückgeben5
).quelle
A
union
ist in einigen Szenarien nützlich.union
kann ein Werkzeug für Manipulationen auf sehr niedriger Ebene sein, wie das Schreiben von Gerätetreibern für einen Kernel.Ein Beispiel dafür ist das Zerlegen einer
float
Zahl unter Verwendungunion
von astruct
mit Bitfeldern und afloat
. Ich spare eine Zahl in derfloat
, und später kann ich bestimmte Teile der Zugrifffloat
durch dasstruct
. Das Beispiel zeigt, wieunion
unterschiedliche Blickwinkel zum Betrachten von Daten verwendet werden.Schauen Sie sich die Beschreibung mit einfacher Genauigkeit auf Wikipedia an. Ich habe das Beispiel und die magische Zahl 0.15625 von dort verwendet.
union
kann auch verwendet werden, um einen algebraischen Datentyp zu implementieren, der mehrere Alternativen aufweist. Ein Beispiel dafür fand ich im Buch "Real World Haskell" von O'Sullivan, Stewart und Goerzen. Überprüfen Sie es im Abschnitt Die diskriminierte Vereinigung .Prost!
quelle
" union " und " struct " sind Konstrukte der C-Sprache. Es ist unangemessen, von einem Unterschied auf "Betriebssystemebene" zu sprechen, da der Compiler unterschiedlichen Code erzeugt, wenn Sie das eine oder andere Schlüsselwort verwenden.
quelle
Nicht technisch gesehen bedeutet:
Annahme: Stuhl = Speicherblock, Personen = Variable
Struktur : Bei 3 Personen können sie entsprechend auf einem Stuhl ihrer Größe sitzen.
Union : Wenn es 3 Personen gibt, nur eine anwesend sind, wird Stuhl zum Sitzen da sein. Alle müssen denselben Stuhl verwenden, wenn sie sitzen möchten.
Technisch bedeutet:
Das unten erwähnte Programm gibt einen tiefen Einblick in Struktur und Vereinigung.
Gesamtgröße MAIN_STRUCT = sizeof (UINT64) für bufferaddr + sizeof (UNIT32) für union + 32 bit für padding (abhängig von der Prozessorarchitektur) = 128 Bit. Für die Struktur erhalten alle Mitglieder den Speicherblock zusammenhängend.
Union erhält einen Speicherblock des Mitglieds mit maximaler Größe (hier 32 Bit). Innerhalb der Union liegt eine weitere Struktur (INNER_STRUCT), deren Mitglieder einen Speicherblock mit einer Gesamtgröße von 32 Bit (16 + 8 + 8) erhalten. In Union kann entweder auf das Mitglied INNER_STRUCT (32 Bit) oder auf Daten (32 Bit) zugegriffen werden.
quelle
Ja, der Hauptunterschied zwischen Struktur und Vereinigung ist der gleiche wie von Ihnen angegeben. Struct verwendet den gesamten Speicher seines Mitglieds und Union den größten Speicherplatz für Mitglieder.
Der Unterschied liegt jedoch in der Nutzung des Speichers. Die beste Verwendung der Union zeigt sich in den Prozessen von Unix, in denen wir Signale verwenden. wie ein Prozess kann immer nur auf ein Signal gleichzeitig einwirken. Die allgemeine Erklärung lautet also:
In diesem Fall verwendet der Prozess nur den höchsten Speicher aller Signale. Wenn Sie in diesem Fall struct verwenden, ist die Speichernutzung die Summe aller Signale. Macht einen großen Unterschied.
Zusammenfassend sollte Union ausgewählt werden, wenn Sie wissen, dass Sie gleichzeitig auf eines der Mitglieder zugreifen.
quelle
Du hast es, das ist alles. Aber was ist der Sinn der Gewerkschaften?
Sie können denselben Standortinhalt verschiedener Typen eingeben. Sie müssen den Typ dessen kennen, was Sie in der Union gespeichert haben (so oft setzen Sie ihn in ein
struct
mit einem Typ-Tag ein ...).Warum ist das wichtig? Nicht wirklich für Platzgewinne. Ja, Sie können ein paar Bits gewinnen oder etwas auffüllen, aber das ist nicht mehr der Hauptpunkt.
Es dient der Typensicherheit und ermöglicht es Ihnen, eine Art "dynamisches Tippen" durchzuführen: Der Compiler weiß, dass Ihr Inhalt unterschiedliche Bedeutungen haben kann und die genaue Bedeutung, wie Ihre Interpretation zur Laufzeit bei Ihnen liegt. Wenn Sie einen Zeiger haben, der auf verschiedene Typen verweisen kann, MÜSSEN Sie eine Union verwenden, da sonst der Code aufgrund von Aliasing-Problemen möglicherweise falsch ist (der Compiler sagt sich: "Oh, nur dieser Zeiger kann auf diesen Typ verweisen, damit ich ihn optimieren kann aus diesen Zugriffen ... ", und schlimme Dinge können passieren).
quelle
Eine Struktur weist die Gesamtgröße aller darin enthaltenen Elemente zu.
Eine Gewerkschaft weist nur so viel Speicher zu, wie ihr größtes Mitglied benötigt.
quelle
Was ist der Unterschied zwischen Struktur und Vereinigung?
Die Antwort lautet: Die Rücksichtnahme liegt in der Speicherzuweisung. Erläuterung: In der Struktur wird Speicherplatz für alle Mitglieder innerhalb der Struktur erstellt. In Union wird Speicherplatz nur für ein Mitglied erstellt, das den größten Speicherplatz benötigt. Betrachten Sie den folgenden Code:
Hier gibt es zwei Mitglieder innerhalb von struct und union: int und long int. Der Speicherplatz für int beträgt: 4 Byte und der Speicherplatz für long int beträgt: 8 im 32-Bit-Betriebssystem.
Für Struktur 4 + 8 = werden 12 Bytes erstellt, während 8 Bytes für die Vereinigung erstellt werden
Codebeispiel:
Ref: http://www.codingpractise.com/home/c-programming/structure-and-union/
quelle
Die Verwendung von Gewerkschaftsverbänden wird häufig verwendet, wenn spezielle Typkonversationen erforderlich sind. Um sich ein Bild von der Nützlichkeit der Vereinigung zu machen. Die c / c-Standardbibliothek definiert keine Funktion, die speziell zum Schreiben kurzer Ganzzahlen in eine Datei entwickelt wurde. Die Verwendung von fwrite () verursacht einen übermäßigen Overhead für eine einfache Bedienung. Mit einer Union können Sie jedoch leicht eine Funktion erstellen, die binär eine kurze Ganzzahl byteweise in eine Datei schreibt. Ich gehe davon aus, dass kurze Ganzzahlen 2 Byte lang sind
DAS BEISPIEL:
Obwohl putw () mit einer kurzen Ganzzahl aufgerufen wurde, war es möglich, putc () und fwrite () zu verwenden. Aber ich wollte ein Beispiel zeigen, um zu dominieren, wie eine Gewerkschaft verwendet werden kann
quelle
Struktur ist die Sammlung verschiedener Datentypen, in denen sich verschiedene Datentypen befinden können und jeder seinen eigenen Speicherblock erhält
Wir haben normalerweise union verwendet, wenn wir sicher sind, dass nur eine der Variablen gleichzeitig verwendet wird und Sie den aktuellen Speicher vollständig nutzen möchten, da nur ein Speicherblock vorhanden ist, der dem größten Typ entspricht.
Gesamtspeicher erhält es => 5 Byte
Gesamtspeicher = 4 Byte
quelle
Gewerkschaften sind praktisch, wenn Sie eine Byte-Bestellfunktion schreiben, die unten angegeben ist. Mit Strukturen ist das nicht möglich.
quelle
Eine Union unterscheidet sich von einer Struktur, da sich eine Union gegenüber den anderen wiederholt: Sie definiert denselben Speicher neu, während die Struktur nacheinander ohne Überlappungen oder Neudefinitionen definiert.
quelle