64 - Declaración de uniones


Ver video

La unión es una estructura de datos muy particular del lenguaje C. La declaración de una unión es similar a un registro (struct):

union dato {
    int x;
    char letra;
    char cadena[5];
};

Como vemos cambiamos la palabra clave struct por union, hasta ahí la semejanza con los registros.

Cuando definimos una variable de un tipo union utilizamos la sintaxis:

union dato d;

La característica fundamental es que se reserva el mismo espacio de memoria para los atributos x, letra y cadena[5].

En una variable de tipo struct cada campo reserva un espacio distinto de memoria en cambio en una unión todas comparten el mismo espacio. Se reserva para el tipo de dato mayor contenida en la unión, si tenemos que x es un int y ocupa 4 bytes, letra es de tipo char y ocupa 1 byte y el vector cadena ocupa 5 bytes luego significa que cuando defino la variable d de tipo union dato se estará reservando 5 bytes de memoria.

Problema 1:

Declarar una unión con tres atributos, uno de tipo int, otro de tipo char y finalmente otro de tipo float.
Definir una variable y guardar en distintos momentos del programa valores para dichos atributos.

Programa: programa206.c

#include<stdio.h>
#include<conio.h>

union dato {
    int x;
    char letra;
    float z;
};

int main()
{
    union dato d;
    d.x=10;
    printf("Impresion del entero:%i\n",d.x);
    d.letra='A';
    printf("Impresion del caracter:%c\n",d.letra);
    printf("Impresion del entero:%i\n",d.x); //El dato se ha modificado
    d.z=5.25;
    printf("Impresion del float:%0.2f\n",d.z);
    printf("Impresion del entero:%i\n",d.x); //El dato se ha modificado nuevamente
    getch();
    return 0;
}

Declaramos una unión llamada dato:

union dato {
    int x;
    char letra;
    float z;
};

En la main definimos una variable:

int main()
{
    union dato d;

Modificamos el atributo x cargando el entero 10:

d.x=10;

Si imprimimos el atributo x luego se muestra el 10:

    printf("Impresion del entero:%i\n",d.x);

Cargamos ahora el atributo letra y almacenamos la 'A':

    d.letra='A';

Si imprimimos el atributo letra el resultado es el esperado, es decir la letra 'A':

    printf("Impresion del caracter:%c\n",d.letra);

Pero si ahora accedemos al atributo x que habíamos almacenado el 10 veremos que ya no tiene dicho valor, esto debido a que los tres atributos comparten el espacio de memoria:

    printf("Impresion del entero:%i\n",d.x); //El dato se ha modificado

Lo mismo sucede cuando modificamos el atributo z y guardamos un valor:

    d.z=5.25;
    printf("Impresion del float:%0.2f\n",d.z);
    printf("Impresion del entero:%i\n",d.x); //El dato se ha modificado nuevamente

En algunas situaciones definimos uniones para poder acceder a los datos con dos modelos distintos. Veremos un ejemplo donde definimos una unión para acceder a dos enteros que representan a un punto en el plano mediante un registro con dos campos y mediante un vector de dos enteros.

Programa: programa207.c

#include<stdio.h>
#include<conio.h>

struct coordenada {
    int x;
    int y;
};

union punto {
    int v[2];
    struct coordenada co;
};


int main()
{
    union punto p;
    p.co.x=10;
    p.co.y=20;
    printf("%i %i\n",p.co.x, p.co.y); //10 20
    printf("%i %i\n",p.v[0],p.v[1]);  //10 20

    getch();
    return 0;
}

Declaramos una unión con dos elementos, uno de tipo vector y otro de tipo registro:

struct coordenada {
    int x;
    int y;
};

union punto {
    int v[2];
    struct coordenada co;
};

En la main definimos una unión y cargamos el elemento co que es un registro:

int main()
{
    union punto p;
    p.co.x=10;
    p.co.y=20;

Ahora podemos acceder a los dos enteros mediante el elemento de tipo registro:

    printf("%i %i\n",p.co.x, p.co.y); //10 20

También podemos acceder a los dos enteros por medio del vector:

    printf("%i %i\n",p.v[0],p.v[1]);  //10 20

Si consultamos el código fuente del sistema operativo Linux en muchos de sus archivos encontraremos declaraciones de uniones:

declaración de union en el código fuente linux

Retornar