I l@ve RuBoard Previous Section Next Section

12.2 Unions

A structure is used to define a data type with several members. Each member takes up a separate storage location. For example, the structure:

struct rectangle { 
    int width; 
    int height; 
}; 

appears in memory as shown in Figure 12-1.

A union is similar to a structure; however, it defines a single location that can be given many different member names:

union value { 
    long int i_value;   // Long integer version of value
    float f_value;      // Floating version of value
} 
Figure 12-1. Structure and union layout
figs/C++2_1201.gif

The members i_value and f_value share the same space. You might think of a structure as a large box divided up into several different compartments, each with its own name. A union is a box, not divided at all, with several different labels placed on the single compartment inside.

In a structure, the members do not interact. Changing one member does not change any others. In a union, all members occupy the same space, so only one may be active at a time. In other words, if you put something in i_value, assigning something to f_value wipes out the old value of i_value.

The following shows how a union may be used:

/* 
 * Define a variable to hold an integer or  
 * a real number (but not both) 
 */ 
union value { 
    long int i_value;   // The real number
    float f_value;      // The floating point number
} data; 

int i;                  // Random integer
float f;                // Random floating point number

int main(  ) 
{ 
    data.f_value = 5.0; 
    data.i_value = 3;   // Data.f_value overwritten

    i = data.i_value;   // Legal

    f = data.f_value;   // Not legal; will generate unexpected results

    data.f_value = 5.5; // Put something in f_value/clobber i_value
    i = data.i_value;   // Not legal; will generate unexpected results
    return (0);
}

Suppose you want to store the information about a shape. The shape can be any standard shape such as a circle, rectangle, or triangle. The information needed to draw a circle is different from the data needed to draw a rectangle, so you need to define different structures for each shape:

struct circle {
    int radius;           // Radius of the circle in pixels
};
struct rectangle {
    int height, width;   // Size of the rectangle in pixels
};
struct triangle {
    int base;            // Length of the triangle's base in pixels
    int height;          // Height of the triangle in pixels
};

Now you define a structure to hold the generic shape. The first member is a code that tells you what type of shape you have. The second is a union that holds the shape information:

const int SHAPE_CIRCLE    = 0;    // Shape is a circle
const int SHAPE_RECTANGLE = 1;    // Shape is a rectangle
const int SHAPE_TRIANGLE  = 2;    // Shape is a triangle

struct shape {
    int kind;               // What kind of shape is stored
    union shape_union {     // Union to hold shape information
        struct circle    circle_data;     // Data for a circle
        struct rectangle rectangle_data;  // Data for a rectangle
        struct triangle  triangle_data;   // Data for a triangle
    } data;
}; 

Graphically you can represent shape as a large box. Inside the box is the single integer kind and our union shape_union. The union is a box with three labels on it. The question is which one is the "real" label. You can't tell from looking at the union, but that's why you defined kind. It tells us which label to read. The layout of the shape structure is illustrated by Figure 12-2.

Figure 12-2. "shape" layout
figs/C++2_1202.gif

Now you can store a circle in the generic shape:

struct shape a_shape;
//...
a_shape.kind = SHAPE_CIRCLE;
a_shape.data.circle_data.radius = 50;  // Define the radius of the circle

In this example we are define one basic data type (a shape) and adding in specific information for a bunch of different types of shapes. Although we are using a union to organize our data, this sort of data can be better organized using base and derived classes. (See Chapter 21.)

    I l@ve RuBoard Previous Section Next Section