Next: Cast to Union, Previous: Unions, Up: Structures [Contents][Index]
Sometimes we design a union with the intention of packing various kinds of objects into a certain amount of memory space. For example.
union bytes8 { long long big_int_elt; double double_elt; struct { int first, second; } two_ints; struct { void *first, *second; } two_ptrs; }; union bytes8 *p;
This union makes it possible to look at 8 bytes of data that p
points to as a single 8-byte integer (p->big_int_elt
), as a
single floating-point number (p->double_elt
), as a pair of
integers (p->two_ints.first
and p->two_ints.second
), or
as a pair of pointers (p->two_ptrs.first
and
p->two_ptrs.second
).
To pack storage with such a union makes assumptions about the sizes of
all the types involved. This particular union was written expecting a
pointer to have the same size as int
. On a machine where one
pointer takes 8 bytes, the code using this union probably won’t work
as expected. The union, as such, will function correctly—if you
store two values through two_ints
and extract them through
two_ints
, you will get the same integers back—but the part of
the program that expects the union to be 8 bytes long could
malfunction, or at least use too much space.
The above example shows one case where a struct
type with no
tag can be useful. Another way to get effectively the same result
is with arrays as members of the union:
union eight_bytes { long long big_int_elt; double double_elt; int two_ints[2]; void *two_ptrs[2]; };