E.12. Unions
A union (defined with keyword union) is a region of memory that, over time, can contain objects of a variety of types. However, at any moment, a union can contain a maximum of one object, because the members of a union share the same storage space. It is the programmer's responsibility to ensure that the data in a union is referenced with a member name of the proper data type.
Common Programming Error E.3
The result of referencing a union member other than the last one stored is undefined. It treats the stored data as a different type. |
Portability Tip E.2
If data are stored in a union as one type and referenced as another type, the results are implementation dependent. |
At different times during a program's execution, some objects might not be relevant, while one other object isso a union shares the space instead of wasting storage on objects that are not being used. The number of bytes used to store a union will be at least enough to hold the largest member.
Performance Tip E.3
Using unions conserves storage. |
Portability Tip E.3
The amount of storage required to store a union is implementation dependent. |
A union is declared in the same format as a struct or a class. For example,
union Number { int x; double y; };
indicates that Number is a union type with members int x and double y. The union definition must precede all functions in which it will be used.
Software Engineering Observation E.4
Like a struct or a class declaration, a union declaration simply creates a new type. Placing a union or struct declaration outside any function does not create a global variable. |
The only valid built-in operations that can be performed on a union are assigning a union to another union of the same type, taking the address (&) of a union and accessing union members using the structure member operator (.) and the structure pointer operator (->). unions cannot be compared.
Common Programming Error E.4
Comparing unions is a compilation error, because the compiler does not know which member of each is active and hence which member of one to compare to which member of the other. |
A union is similar to a class in that it can have a constructor to initialize any of its members. A union that has no constructor can be initialized with another union of the same type, with an expression of the type of the first member of the union or with an initializer (enclosed in braces) of the type of the first member of the union. unions can have other member functions, such as destructors, but a union's member functions cannot be declared virtual. The members of a union are public by default.
Common Programming Error E.5
Initializing a union in a declaration with a value or an expression whose type is different from the type of the union's first member is a compilation error. |
A union cannot be used as a base class in inheritance (i.e., classes cannot be derived from unions). unions can have objects as members only if these objects do not have a constructor, a destructor or an overloaded assignment operator. None of a union's data members can be declared static.
Figure E.8 uses the variable value of type union Number to display the value stored in the union as both an int and a double. The program output is implementation dependent. The program output shows that the internal representation of a double value can be quite different from the representation of an int.
Figure E.8. Printing the value of a union in both member data types.
(This item is displayed on pages 1264 - 1265 in the print version)
1 // Fig. E.8: figE_08.cpp 2 // An example of a union. 3 #include 4 using std::cout; 5 using std::endl; 6 7 // define union Number 8 union Number 9 { 10 int integer1; 11 double double1; 12 }; // end union Number 13 14 int main() 15 { 16 Number value; // union variable 17 18 value.integer1 = 100; // assign 100 to member integer1 19 20 cout << "Put a value in the integer member " 21 << "and print both members. int: " 22 << value.integer1 << " double: " << value.double1 23 << endl; 24 25 value.double1 = 100.0; // assign 100.0 to member double1 26 27 cout << "Put a value in the floating member " 28 << "and print both members. int: " 29 << value.integer1 << " double: " << value.double1 30 << endl; 31 32 return 0; 33 } // end main
|
An anonymous union is a union without a type name that does not attempt to define objects or pointers before its terminating semicolon. Such a union does not create a type but does create an unnamed object. An anonymous union's members may be accessed directly in the scope in which the anonymous union is declared just as are any other local variablesthere is no need to use the dot (.) or arrow (->) operators.
Anonymous unions have some restrictions. Anonymous unions can contain only data members. All members of an anonymous union must be public. And an anonymous union declared globally (i.e., at file scope) must be explicitly declared static. Figure E.9 illustrates the use of an anonymous union.
Figure E.9. Using an anonymous union.
(This item is displayed on pages 1265 - 1266 in the print version)
1 // Fig. E.9: figE_09.cpp 2 // Using an anonymous union. 3 #include 4 using std::cout; 5 using std::endl; 6 7 int main() 8 { 9 // declare an anonymous union 10 // members integer1, double1 and charPtr share the same space 11 union 12 { 13 int integer1; 14 double double1; 15 char *charPtr; 16 }; // end anonymous union 17 18 // declare local variables 19 int integer2 = 1; 20 double double2 = 3.3; 21 char *char2Ptr = "Anonymous"; 22 23 // assign value to each union member 24 // successively and print each 25 cout << integer2 << ' '; 26 integer1 = 2; 27 cout << integer1 << endl; 28 29 cout << double2 << ' '; 30 double1 = 4.4; 31 cout << double1 << endl; 32 33 cout << char2Ptr << ' '; 34 charPtr = "union"; 35 cout << charPtr << endl; 36 37 return 0; 38 } // end main
|