Unions

A union is a user-defined data type. It is similar to a structure in that it can have any number of members, each with its own data type. The difference between a union and a structure is that all of the members of a union occupy the same space in memory. A union can therefore only contain one object from its list of members at any given time (although the object can be a complex data type such as an array or structure). A union is declared using the following format:

typedef union
{
  type member_name_1;
  type member_name_2;
  type member_name_3;
  . . .
} my_union;

In the above example my_union is the name given to the union type. The member elements of the union and their data types are listed between the curly braces ({ }). The amount of memory allocated to the union will be sufficient to store the data type of the largest member of the union. Consider the following declaration:

typedef union
{
  char category;
  int count;
  double price;
}my_union;

my_union my_union_var;

In this example, the member with the largest data type is price, which is a double-precision floating point number, so the union occupies eight bytes (the size of the data type double) in memory. In order to work with a union member, you must identify both the union object and the member element with which you wish to work. The following program statements demonstrate two alternative uses of the my_union_var variable declared above:

my_union_var.count = 27;   // used as type int
my_union_var.price = 2.49; // used as type double

Note that in each statement, the member element is referenced using the object's name, and the name of the member element, separated by a period. The following short program demonstrates the use of unions (note that you can declare and initialise a union at the same time):

// Example program
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

typedef union
{
  int var1;
  double var2;
}my_union;

void main()
{
  my_union my_numbers = {10}; // var1 = 10
  printf("my_numbers.var1 evaluates to: %d", my_numbers.var1);
  printf("\n\nPress ENTER to continue.");
  getch();
  my_numbers.var2 = 3.141592653589;
  printf("\n\nmy_numbers.var2 evaluates to: %f", my_numbers.var2);
  printf("\n\nPress any key to exit . . . ");
  getch();
}

The output from the example program is shown below:


The output from the example program

The output from the example program


Unions are a powerful, if rarely-used feature of C. They allow the same area of memory to be used for different purposes, which is a useful feature if the available memory is limited (as is often the case in embedded systems). Each new value that is assigned to a union member variable overwrites, at least partially, any value already stored there.

It is important to keep track of what data type is currently stored in a union variable, since attempting to retrieve a value of the wrong type will often produce meaningless data. For example, if a large union member (let’s say a structure) is replaced by a smaller union member (say an integer), the structure data will be partially over-written. Any subsequent attempt to retrieve the structure will have unpredictable results.

Unions and structures are perhaps most often used together to allow very small data elements (individual bits, or small groupings of bits) to be accessed and manipulated. An 8 bit, 16-bit, 32-bit or larger numeric variable type may often be defined within a union together with a structure that occupies the same space, but defines a collection of bit-fields, each of which consists of one or more bits (bit fields may only be members of unions or structures).

A typical use of this arrangement is to get the contents of a computer register (the size of which will be hardware-dependent) into a union member variable having a standard data type (e.g. int or long int), and then access individual bit-fields using another union member, namely a structure that defines them. The subject of bit-fields will not be pursued further here.