健康快乐 虚怀若谷 淡定从容
分类: C/C++
2011-10-12 14:52:20
A union is a type that enables you to store different data types in the same memory space (but not simultaneously). A typical use is a table designed to hold a mixture of types in some order that is neither regular nor known in advance. By using an array of unions, you can create an array of equal-sized units, each of which can hold a variety of data types. Unions are set up in much the same way as structures. There is a union template and a union variable. They can be defined in one step or, by using a union tag, in two. Here is an example of a union template with a tag: union hold { int digit; double bigfl; char letter; }; A structure with a similar declaration would be able to hold an int value and a double value and a char value. This union, however, can hold an int value or a double value or a char value. Here is an example of defining three union variables of the hold type: union hold fit; // union variable of hold type union hold save[10]; // array of 10 union variables union hold * pu; // pointer to a variable of hold type
The first declaration creates a single variable, fit. The compiler allots enough space so that it can hold the largest of the described possibilities. In this case, the biggest possibility listed is double, which requires 64 bits, or 8 bytes, on our system. The second declaration creates an array called save with 10 elements, each 8 bytes in size. The third declaration creates a pointer that can hold the address of a hold union. You can initialize a union. Because the union holds only one value, the rules are different from those in a structure. In particular, you have three choices: You can initialize a union to another union of the same type, you can initialize the first element of a union, or, with C99, you can use a designated initializer: union hold valA; valA.letter = 'R'; union hold valB = valA; // initialize one union to another union hold valC = {88}; // initialize digit member of union union hold valD = {.bigfl = 118.2}; // designated initializer
Here is how you can use a union: fit.digit = 23; // 23 is stored in fit; 2 bytes used fit.bigfl = 2.0; // 23 cleared, 2.0 stored; 8 bytes used fit.letter = 'h'; // 2.0 cleared, h stored; 1 byte used
The dot operator shows which data type is being used. Only one value is stored at a time. You can't store a char and an int at the same time, even though there is enough space to do so. It is your responsibility to keep track of the data type currently being stored in a union. You can use the -> operator with pointers to unions in the same fashion that you use the operator with pointers to structures: pu = &fit; x = pu->digit; // same as x = fit.digit
The next sequence shows what not to do: fit.letter = 'A'; flnum = 3.02*fit.bigfl; // ERROR ERROR ERROR
This sequence is wrong because a char type is stored, but the next line assumes that the content of fit is a double type. However, sometimes it can be useful to use one member to place values into a union and to then use a different member for viewing the contents. in the next chapter shows an example. Another place you might use a union is in a structure for which the stored information depends on one of the members. For example, suppose you have a structure representing an automobile. If the automobile is owned by the user, you want a structure member describing the owner. If the automobile is leased, you want the member to describe the leasing company. Then you can do something along the following lines: struct owner { char socsecurity[12]; ... }; struct leasecompany { char name[40]; char headquarters[40]; ... }; union data { struct owner owncar; struct leasecompany leasecar; }; struct car_data { char make[15]; int status; /* 0 = owned, 1 = leased */ union data ownerinfo; ... };
Suppose flits is a car_data structure. Then if flits.status were 0, the program could use flits.ownerinfo.owncar.socsecurity, and if flits.status were 1, the program could use flits.ownerinfo.leasecar.name.
|