C Language
Gewerkschaften
Suche…
Unterschied zwischen struct und union
Dies zeigt, dass Gewerkschaftsmitglieder Speicher gemeinsam nutzen und dass Strukturmitglieder Speicher nicht gemeinsam nutzen.
#include <stdio.h>
#include <string.h>
union My_Union
{
int variable_1;
int variable_2;
};
struct My_Struct
{
int variable_1;
int variable_2;
};
int main (void)
{
union My_Union u;
struct My_Struct s;
u.variable_1 = 1;
u.variable_2 = 2;
s.variable_1 = 1;
s.variable_2 = 2;
printf ("u.variable_1: %i\n", u.variable_1);
printf ("u.variable_2: %i\n", u.variable_2);
printf ("s.variable_1: %i\n", s.variable_1);
printf ("s.variable_2: %i\n", s.variable_2);
printf ("sizeof (union My_Union): %i\n", sizeof (union My_Union));
printf ("sizeof (struct My_Struct): %i\n", sizeof (struct My_Struct));
return 0;
}
Verwendung von Vereinigungen, um Werte neu zu interpretieren
Einige C-Implementierungen erlauben es dem Code, in ein Mitglied eines Unionstyps zu schreiben und dann von einem anderen zu lesen, um eine Art Neuinterpretation der Besetzung durchzuführen (Parsen des neuen Typs als Bitdarstellung des alten).
Beachten Sie jedoch, dass dies vom aktuellen oder früheren C-Standard nicht zulässig ist und zu undefiniertem Verhalten führt. Dies ist jedoch eine sehr häufige Erweiterung, die von Compilern angeboten wird (überprüfen Sie daher die Compiler-Dokumente, wenn Sie dies vorhaben.) .
Ein reales Beispiel für diese Technik ist der "Fast Inverse Square Root" -Algorithmus, der sich auf Implementierungsdetails von IEEE 754-Gleitkommazahlen stützt, um eine inverse Quadratwurzel schneller als mit Gleitkommaoperationen auszuführen. Dieser Algorithmus kann entweder durch Zeigergießen ausgeführt werden (was sehr gefährlich ist und gegen die strikte Aliasing-Regel verstößt) oder durch eine union (was immer noch undefiniertes Verhalten ist, aber in vielen Compilern funktioniert):
union floatToInt
{
int32_t intMember;
float floatMember; /* Float must be 32 bits IEEE 754 for this to work */
};
float inverseSquareRoot(float input)
{
union floatToInt x;
int32_t i;
float f;
x.floatMember = input; /* Assign to the float member */
i = x.intMember; /* Read back from the integer member */
i = 0x5f3759df - (i >> 1);
x.intMember = i; /* Assign to the integer member */
f = x.floatMember; /* Read back from the float member */
f = f * (1.5f - input * 0.5f * f * f);
return f * (1.5f - input * 0.5f * f * f);
}
Diese Technik wurde in der Vergangenheit aufgrund ihrer höheren Geschwindigkeit im Vergleich zu Fließkommaoperationen häufig in Computergrafiken und Spielen verwendet und stellt einen Kompromiss dar. Sie verliert an Genauigkeit und ist im Gegenzug für Geschwindigkeit nicht tragbar.
Einem Gewerkschaftsmitglied schreiben und von einem anderen lesen
Die Mitglieder einer Gewerkschaft teilen sich den gleichen Speicherplatz. Das bedeutet, dass das Schreiben an ein Mitglied die Daten aller anderen Mitglieder überschreibt und dass das Lesen eines Mitglieds die gleichen Daten ergibt wie das Lesen aller anderen Mitglieder. Da Gewerkschaftsmitglieder jedoch unterschiedliche Typen und Größen haben können, können die gelesenen Daten unterschiedlich interpretiert werden, siehe http://www.riptutorial.com/c/example/9399/using-unions-to-reinterpret-values
Das folgende einfache Beispiel zeigt eine Vereinigung mit zwei Mitgliedern des gleichen Typs. Es zeigt, dass das Schreiben in Member m_1
führt, dass der geschriebene Wert aus Member m_2
gelesen wird, und das Schreiben in Member m_2
führt, dass der geschriebene Wert aus Member m_1
gelesen wird.
#include <stdio.h>
union my_union /* Define union */
{
int m_1;
int m_2;
};
int main (void)
{
union my_union u; /* Declare union */
u.m_1 = 1; /* Write to m_1 */
printf("u.m_2: %i\n", u.m_2); /* Read from m_2 */
u.m_2 = 2; /* Write to m_2 */
printf("u.m_1: %i\n", u.m_1); /* Read from m_1 */
return 0;
}
Ergebnis
u.m_2: 1
u.m_1: 2