C Language
Les syndicats
Recherche…
Différence entre struct et union
Cela montre que les membres d'union partagent la mémoire et que les membres de la structure ne partagent pas la mémoire.
#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;
}
Utiliser les unions pour réinterpréter les valeurs
Certaines implémentations C permettent au code d'écrire sur un membre d'un type d'union puis de lire sur un autre afin d'effectuer une sorte de réinterprétation du cast (analyse du nouveau type en tant que représentation binaire de l'ancien).
Il est important de noter que ceci n'est pas autorisé par la norme C actuelle ou passée et entraînera un comportement indéfini, mais les compilateurs proposent néanmoins une extension très commune (vérifiez donc vos documents de compilation si vous envisagez de le faire). .
Un exemple réel de cette technique est l'algorithme "Racine Carré Inverse Rapide" qui repose sur les détails d'implémentation des nombres à virgule flottante IEEE 754 pour effectuer une racine carrée inverse plus rapide que l'utilisation des opérations à virgule flottante. (ce qui est très dangereux et enfreint la règle de l'aliasing strict) ou par une union (qui est toujours un comportement non défini mais fonctionne dans de nombreux compilateurs):
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);
}
Cette technique était largement utilisée en infographie et dans les jeux dans le passé en raison de sa plus grande rapidité par rapport aux opérations en virgule flottante.
Écrire à un membre du syndicat et lire d'un autre membre
Les membres d'un syndicat partagent le même espace en mémoire. Cela signifie que l'écriture sur un membre écrase les données dans tous les autres membres et que la lecture d'un membre entraîne les mêmes données que la lecture de tous les autres membres. Cependant, comme les membres d'union peuvent avoir différents types et tailles, les données lues peuvent être interprétées différemment, voir http://www.riptutorial.com/c/example/9399/using-unions-to-reinterpret-values
L'exemple simple ci-dessous montre une union avec deux membres, tous deux du même type. Cela montre que l'écriture dans le membre m_1
entraîne la lecture de la valeur écrite du membre m_2
et l'écriture dans le membre m_2
entraîne la lecture de la valeur écrite du membre m_1
.
#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;
}
Résultat
u.m_2: 1
u.m_1: 2