I l @ ve RuBoard |
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 layoutThe 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" layoutNow 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 |