Wrox Press C++ Tutorial


Sharing Memory Between Variables

As a relic of the days when 64K was quite a lot of memory, we have a facility in C++ which allows more than one variable to share the same memory (but obviously not at the same time). This is called a union, and there are three basic ways in which you can use one:

Defining Unions

A union is defined using the keyword union. It is best understood by taking an example of a definition:

union shareLD        // Sharing memory between long and double
{
   double dval;
   long lval;
};

This defines a union type shareLD which provides for the variables of type long and double to occupy the same memory. The union type name is usually referred to as a tag name. This statement is rather like a class definition, in that we haven't actually defined a union instance yet, so we don't have any variables at this point. Once it has been defined, we can declare instances of a union in a declaration. For example:

shareLD MyUnion;

This declares an instance of the union, shareLD, that we defined previously. We could also have declared MyUnion by including it in the union definition statement:

union shareLD          // Sharing memory between long and double
{
   double dval;
   long lval;
} MyUnion;

If we want to refer to a member of the union, we use the direct member selection operator (the period) with the union instance name, just as we have done when accessing members of a class. So, we could set the long variable lval to 100 in the union instance MyUnion with this statement:

MyUnion.lval = 100;       // Using a member of a union

The basic problem with using a union to store different types of values in the same memory is that, because of the way a union works, you also need some means of determining which of the member values is current. This is usually achieved by maintaining another variable which acts as an indicator of the type of value stored.

A union is not limited to sharing between two variables. If you wish, you can share the same memory between several variables. The memory occupied by the union will be that which is required by its largest member. For example, if we define this union,

union shareDLF
{
   double dval;
   long lval;
   float fval;
} uinst = {1.5};

it will occupy 8 bytes, as illustrated in the figure here:

In the example, we defined an instance of the union, uinst, as well as the tag name for the union. We also initialized it with the value 1.5.

You can only initialize the first member of the union when you declare an instance.

Anonymous Unions

You can define a union without a union type name, in which case an instance of the union is automatically declared. For example, if we define a union like this,

union
{
   char* pval;
   double dval;
   long lval;
};

it defines both a union with no name and an instance of the union with no name. Consequently, the variables that it contains may be referred to just by their names, as they appear in the union definition. This can be more convenient than a normal union with a type name, but you need to be careful that you don't confuse the members with ordinary variables. The members of the union will still share the same memory. As an illustration of how the anonymous union above works, to use the double member, you could write this statement:

dval = 99.5;     // Using a member of an anonymous union

As you can see, there's nothing to distinguish the variable dval as a union member. If you need to use anonymous unions, you could use a naming convention to make the members more obvious.

Unions in Classes

You can include an instance of a union in a class. If you intend storing different types of value at different times, this usually necessitates maintaining a class data member to indicate what kind of value is stored in the union. There isn't usually a great deal to be gained by using unions as class members.


© 1998 Wrox Press