Tuesday, July 1, 2014

Uses of Union in C

A union is a special data type available in C/C++ that enable user to store different data types in the same memory location. User can define a union with many members, but only one member can contain a value at any given time. Union thus provide an efficient way of using the same memory location for multiple types. Unions are quite similar to the structures in C but there is difference in memory allocation, memory required to store a union variable is the memory required for largest element of an union. Whereas, to store a structure variables, memory required is the sum of memory size of all members.

Union data type is quite useful in C. Unions in C are used for type-safe polymorphism. In C++'s use of classes & inheritance make the need of Union redundant.

Because of above mentioned properties Unions are mostly used for


1. Creating own Variant type

A variant can be thought of as a container that can hold a variable of almost any data type be it a numeric, float, string, or even an entire array. To create your own variant type, a union can be encapsulated within a structure along with a discriminator that indicates which of the fields of the union are valid. 
 typedef enum {EMPTY, CHAR, INT, UINT, FLOAT, DOUBLE, PTR} ValueType; 
 struct variant_t {
    int mType;
    union {
        char charVal;
        int intVal;
        unsigned int uintVal;
        float floatVal;
        double doubleVal;
        void* ptrVal;
    };
};

it can be then used as,
/* Read a value to the variant from some record */
void getData(struct variant_t* v, int variantType)
{
v->mType = (ValueType)variantType;
switch(v->mType)
{
case CHAR:
v->charVal = ReadData(fptr);
break;
case DOUBLE:
v->doubleVal = ReadData(fptr);
break;
}

2. In embedded systems.
In the embedded realm, each bit of a register may mean different things. In such scenarios a union of a 1 byte char and a structure with 8 separate 1 bit bit-fields , allows you to either change one bit or the entire byte.
Similar examples can be found in many networking APIs for IPv4 address like
union ipv4Addr {
  unsigned  ipAddress;
  char      octets[4];
};

3. To cast pointer to an int and vice-versa
In the embedded realm, mostly the size of a pointer and an int are same. This is because both of them can fit into a CPU register. So if you want to store a value at a particular memory location, you can do something like this
typedef union {
   int i;
   int* iptr;
 }intptr;

 intptr p;

 p.i = 256;
 *(p.iptr)=5; /* put 5 a location 256 */ 

 when we set p.i = 256; both the members of union has value 256, since each member share same location.


 An example C code build using VS2010 IDE can be downloaded from here. In this code a student record in "data.txt" file is read and stored in linked list. Each node of list has a union to store student information. The requirement is that, at a time user want to display only one of either name, roll number, grades or result. So depending on what user want to display, data is stored in Node that store a only a particular type ( Variant ) and display only that particular type of data.