7.3.- Uniones
Los tipos union comparten muchas de las características sintácticas y funcionales de los tipos struct, sin embargo existen algunas diferencias; la principal es que la union permite que solamente uno de sus miembros esté activo a la vez, mientras que en la estructura todos los miembros están activos al mismo tiempo. Otra diferencia es que el tamaño de la union es el tamaño del miembro más grande, mientras que en la estructura su tamaño es la suma de los tamaños de sus miembros.
Las uniones son recomendables cuando se van a manejar variables que pueden compartir espacio en la memoria, debido a que sus valores van a requerirse en momentos diferentes.
Por ejemplo, sean tres variables :
una de tipo int,
otra de tipo float,
y otra de tipo double.
Si no van a manejarse simultáneamente, puede definirse un nuevo tipo union que las abarque, así:
union nums {
int x ; // 2 bytes
float y ; // 4 bytes
double z ; // 8 bytes
} ;
En este momento se cuenta con un nuevo tipo llamado nums, así que podemos utilizarlo para efectuar la siguiente declaración:
nums varnums ; // Se declara la variable varnums
// que ocupa 8 bytes de memoria.
Se pueden accesar los miembros de varnums a través del operador punto, por ejemplo :
varnums.x = 10 ; // Se asigna el valor 10 al miembro
// x de la union varnums.
En el listado 7.5 se muestra un programa completo para el manejo de este ejemplo.
#include <iostream.h>
void main()
{
union nums{
int x ;
float y ;
double z ;
};
nums varnums ;
varnums.y = 200000.125 ;
varnums.z = 3000000.3333 ;
varnums.x = 10 ;
// Despliega el valor 10 y dos valores inesperados.
cout << varnums.x << " " << varnums.y ; cout << " " << varnums.z << "\n" ; varnums.x="10" ; varnums.z="3000000.3333" ; varnums.y="200000.125" ; // Despliega un valor inesperado, el valor 200000.125 y // un valor inesperado. cout << varnums.x << " " << varnums.y ; cout << " " << varnums.z << "\n" ; varnums.x="10" ; varnums.y="200000.125" ; varnums.z="3000000.3333" ; // Despliega dos valores inesperados y 3000000.3333 cout << varnums.x << " " << varnums.y ; cout << " " << varnums.z << "\n" ; }
Listado 7.5.- Acceso a los miembros de una union
Los miembros de una union pueden ser de cualquier tipo, incluyendo estructuras, como se muestra en el listado 7.6.
#include <iostream.h>
#include <dos.h> // Para int86()
void main()
{
REGS regs;
unsigned int tam ;
int86(0x12, ®s, ®s) ;
tam = regs.x.ax ;
cout << "\nEl tamaño de la memoria convencional es de " ; cout << tam << " KiloBytes\n" ; }
Listado 7.6.- Uso de estructuras dentro de uniones.
La union REGS está definida en el archivo dos.h de la siguiente forma :
struct WORDREGS
{
unsigned int ax, bx, cx, dx, si, di, flags ;
};
struct BYTEREGS
{
unsigned char al, ah, bl, bh, cl, ch, dl, dh ;
};
union REGS
{
WORDREGS x ;
BYTEREGS h ;
};
Puede declararse una union sin etiqueta, y en tal caso se le llama union anónima. En el listado 7.7 se muestra un ejemplo.
#include
void main()
{
union { // Nótese la ausencia de etiqueta
int a ;
char b ;
}; // No se ha definido un tipo union, sino una
// union anónima.
a=1 ; // Se accesan los miembros sin utilizar
b='X'; // el operador punto, ya que no existe
// un identificador para la union.
// Despliega un valor inesperado y el valor X
cout << a << " " << b << "\n"; b="X" ; a="1" ; // Despliega el valor 1 y un valor inesperado cout << a << " " << b << "\n"; }
Listado 7.7.- Manejo de uniones anónimas.