C Language
Uniones
Buscar..
Diferencia entre estructura y unión.
Esto ilustra que los miembros de la unión comparten memoria y que los miembros de la estructura no comparten memoria.
#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;
}
Uso de uniones para reinterpretar valores.
Algunas implementaciones de C permiten que el código escriba en un miembro de un tipo de unión y luego lea de otro para realizar una especie de reinterpretación de la conversión (analizando el nuevo tipo como la representación de bits del antiguo).
Es importante tener en cuenta, sin embargo, esto no está permitido por el estándar C actual o el pasado y dará lugar a un comportamiento indefinido, sin embargo, es una extensión muy común ofrecida por los compiladores (así que verifique los documentos de su compilador si planea hacerlo) .
Un ejemplo real de esta técnica es el algoritmo de "Raíz Cuadrada Inversa Rápida", que se basa en los detalles de implementación de los números de punto flotante IEEE 754 para realizar una raíz cuadrada inversa más rápidamente que mediante operaciones de punto flotante. Este algoritmo se puede realizar a través del lanzamiento de punteros. (que es muy peligroso y rompe la regla estricta de aliasing) o a través de una unión (que sigue siendo un comportamiento indefinido pero funciona en muchos compiladores):
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);
}
Esta técnica fue ampliamente utilizada en gráficos y juegos de computadora en el pasado debido a su mayor velocidad en comparación con el uso de operaciones de punto flotante, y es en gran medida un compromiso, perdiendo cierta precisión y siendo muy poco portátil a cambio de la velocidad.
Escribir a un miembro del sindicato y leer de otro.
Los miembros de un sindicato comparten el mismo espacio en la memoria. Esto significa que al escribir en un miembro se sobrescriben los datos en todos los demás miembros y que la lectura de un miembro da como resultado la misma información que la lectura de todos los demás miembros. Sin embargo, dado que los miembros de la unión pueden tener diferentes tipos y tamaños, los datos que se leen pueden interpretarse de manera diferente, consulte http://www.riptutorial.com/c/example/9399/using-unions-to-reinterpret-values
El ejemplo simple a continuación demuestra una unión con dos miembros, ambos del mismo tipo. Muestra que escribir en el miembro m_1
hace que el valor escrito se lea del miembro m_2
y que escribir en el miembro m_2
resultado que el valor escrito se lea en el miembro 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;
}
Resultado
u.m_2: 1
u.m_1: 2