Unions in C

By : |October 19, 2000 0



Size of structures
Structures, arrays and unions (that’s explained next), are used to create
variables of large sizes but the actual size of these variables in terms of
bytes may vary from machine to machine. To tell us the actual size of these
variables we can make use of the unary operator sizeof. For that matter,
it can also be used to determine the size of any variable like integer or float
or character etc.
 sizeof(struct product);

This will return the number of bytes required to hold all the members of the
structure product. If we declare a structure variable item of type struct
then the expression sizeof(item) will return the same value.
One very important use of this is that it can help determine  the number of
records in a database. Let’s say that item is an array variable of type
struct product, then sizeof(item) would give the total number of bytes
the array item requires. Then

___________________________________________________________________________________________________________

 sizeof(item)/sizeof(struct product) would give the number of
elements in the array item.

Unions
Now that we’re through with structures, unions should be very simple to
follow. The syntax for unions is similar to structures. But why do we need the
union datatype if it’s so similar to structures? The difference between
structures and unions is in storage, and the main objective of the union
datatype is to conserve memory. Unlike in structures where each member has its
own storage location, the members of a union share the same storage area within
the computer’s memory. In other words, although a union may contain members of
different datatypes it can handle only one member at one time. Let’s take a
look at the declaration:
 union tag
 {
   datatype member1;
   datatype member2;
   ……..
   ……..
   datatype member n;
 }variable1,variable2……..variable n;

 union products
 {
   int num;
   float rate;
   char code;
 }prod1;

In the above example, the variable prod1 is of type union products and
can represent either the integer num, float rate or the character code at any
given time and we can use only one of them at a time. This is because the
compiler allocates enough memory only to hold the largest variable type in the
union. In the example above, the datatype float requires 4bytes which is the
largest among the members, thus only 4bytes are assigned and all three variables
share this same 4bytes. So, let’s say the member rate was allocated memory from
the address 4000 to 4003 then the member num would share the memory locations
4000 and 4001 while code would share the location 4000. So, all the three
variables share the same address. We can verify this by using the sizeof
operator.
 main()
 {
   int x;
   x=sizeof( prod1);
 }
In the above expression, the variable x will contain the number of bytes of
memory required by the largest member which in this case is rate of the float
datatype, so x will contain the value 4.
A union member can be accessed in the same manner as a structure member using
the dot operator.
 prod1.num

But while accessing, we should make sure that we access that member whose value
is currently stored. For e.g..
 prod1.num=100;
 prod1.rate=190.55;
 printf(“%d”,prod1.num);

This would produce erroneous output. This is because prod1.rate supercedes
the previous member prod1.num.

Bit fields
We’ve used integer variables of size 2 bytes or 16 bits to store data. But
it’s not necessary for data items to require 16 bits space, they could occupy
much less. In such cases, memory space is wasted. To overcome this, small bit
fields can be used to store data items and thereby pack several data items in a
word of memory. Bit fields not only conserve memory but also allow direct
manipulation of a string of pre-selected bits as if it represented an integral
quantity.

A bit field is a set of adjacent bits whose size can be from 1 to 16 bits in
length. A word can therefore be divided into a number of bit fields. The name
and size of bit fields are defined using a structure. The general form of bit
field definition is as follows:
 struct tag_name
 {
   datatype member1: bit_length;
   datatype member2: bit_length;
   ……….
   ……….
   datatype member n: bit_length;
 };
Here the datatype of the member can be int or unsigned int or signed int
and the bit_length is the number of bits required by that member. The signed bit
field should have at least 2 bits, one for the data and the other for the sign.
The member name should be followed by a colon. The bit_length is decided by the
range of value to be stored and the largest value that can be stored is 2 to the
power of n-1, where n is bit_length.

The internal representation of bit fields is machine dependant and depends on
the size of int and ordering of bits. Some machines may store the bits from left
to right while others might do so from right to left.

Note:
1. The first field always starts with the first bit of the word.
2. The sum of lengths of all the fields in a structure should not be more than
the size of a word. In case it’s more,  the overlapping field is
automatically forced to the beginning of the next word.
3. There can be unnamed fields declared with just the size.
4. There can be unused bits in a word.
5.  We cannot access the address of a bit field variable. Hence, we cannot
use scanf to accept values into bit fields. 
6. Bit fields cannot be arrayed.
7. If we assign values to bit fields larger than their range, behavior is
unpredictable.

Using the example of an employee database, we store all the information in
the compressed form as follows:
 struct emp_base
 {
   unsigned age: 7;
   unsigned m_status: 1;
   unsigned sex: 1;
   unsigned: 4;
 }emp;
This defines a variable emp of type struct emp_base with 4 bit fields, the range of values of each of these members is as follows: age can take the range of values 0-127 (2 to the power of the bit_length -1), while m_status can take values 0 or 1 similarly for sex. Now to access the fields, we can follow the same method as in the case of ordinary structure members using the period operator.

     emp.age=50;

Now if you want to read in the values from the keyboard you will have to read into a temporary variable and then assign its value to the bit field since scanf cannot be used.

No Comments so fars

Jump into a conversation

No Comments Yet!

You can be the one to start a conversation.