Advertisment

Unions in C

author-image
CIOL Bureau
Updated On
New Update

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.






Advertisment

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.

Advertisment

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.

Advertisment

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.

tech-news