Choosing Between Structs and Unions
A union is a struct in which all members are allocated at the same address.
A Symbol Table Design Problem
Imagine a compiler keeping a symbol table, where each entry describes one identifier in a program. Every entry needs a name, and it also needs a value. The name is always text. The value, however, may be a number in one case and something else in another. This is a design tension: you want one record to describe the entry, yet only one kind of information is meaningful in a given entry at any moment.
What do you think happens?
If each symbol table entry holds a name and a value that is sometimes a number and sometimes something else, must the record have room for both kinds of value at the same time?
Reveal answer
Not necessarily. Only one kind of value is meaningful in a given entry at any moment, which is the situation a union is designed for.
The name always needs its own storage, but the value only needs to hold one interpretation at a time. A union lets several alternatives share one region of storage instead of each reserving separate space.
Where Struct Members Live
A union is a struct in which all members are allocated at the same address.
The easiest way to understand a union is to contrast it with a struct. A struct gives every member its own region of memory, so a struct holding a name and a value has room for both at once. A union turns that arrangement around. Its members are all allocated at the same address, so the union does not reserve separate space for each member. Instead, the storage is shared.
Read the diagram column by column. The struct column has two separate regions, one for each member. The union column has one shared region, and both of its members point into it. Because the members overlap, writing to one member affects the storage the other members would otherwise use. This overlap is the central difference between the two structures.
Tracing the Shared Region
Because every member of a union occupies the same region, the union can hold a value for only one member at a time. Storing a value through one member replaces whatever was previously in that shared region. The other members therefore no longer hold a meaningful value.
What do you think happens?
After a number is written through the count member, a text value is written through the name member. What do you get when you then read the count member?
Reveal answer
You get whatever bits happen to be in the shared storage, which is generally not the number you originally stored.
Reading a different member than the one most recently written returns the bits in the shared region, interpreted through that member. Those bits were last set by the name write, so the count value is gone.
Working Out a Union's Size
A union occupies only as much space as its largest member. It does not add the member sizes together, and it does not grow when you add a member that fits inside the existing region. The question to ask is always which member is the biggest. If the member sizes are $s_1, s_2, \ldots, s_n$, the size of the union is the largest of them:
Sizing a union with three members
A union has three members whose sizes are 4 bytes, 8 bytes, and 2 bytes. How many bytes of memory does the union occupy?
- 1List the member sizes
The sizes are 4, 8, and 2 bytes.
- 2Find the largest member
The largest is the 8-byte member.
- 3Ignore the sum
Adding them gives 14 bytes, but the union does not reserve space for all members together. Only the largest member sets the size.
- 4State the size
All members start at the same address, so the region must be large enough for the 8-byte member. The union occupies 8 bytes.
The union occupies 8 bytes.
The diagram stacks the members on one shared starting point, not end to end. The 4-byte and 2-byte members fit inside the region that the 8-byte member already requires, so they add nothing to the total.
Mistakes With Shared Members
Common mistake Adding the member sizes to find the size of a union
What it looks likeFor members of 4, 8, and 2 bytes, computing 4 + 8 + 2 = 14 bytes.
Why it failsMembers of a union share storage rather than receiving separate regions, so their sizes are not summed.
Do this insteadFind the largest member. For these members the union occupies 8 bytes.
Common mistake Expecting every member to keep its value after one member is written
What it looks likeWriting a number through one member and then a text value through another, and assuming the number is still readable.
Why it failsEvery member occupies the same region, so storing through one member replaces what was in the shared region.
Do this insteadTreat a union as holding one meaningful value at a time, and read the member that was most recently written.
Common mistake Reading a different member than the one last written and trusting the result
What it looks likeWriting through the name member and then reading the value member as if it were a valid number.
Why it failsThe bits in the shared region are generally not the value you expect when read through a different member.
Do this insteadRead the same member you last wrote, or make sure your design knows which member is currently meaningful.
Choosing Struct or Union
The choice depends on whether all members need to hold values at the same time. A struct suits situations where every member is meaningful together, since each member has its own region. A union suits situations where only one of several alternatives is meaningful at any moment, and where sharing storage saves space, as in the symbol table entry.
| Question | Struct | Union |
|---|---|---|
| Where are the members placed? | Each member has its own region | All members are allocated at the same address |
| How much space is occupied? | Room for all members together | Only as much as the largest member |
| How many members hold values at once? | All of them | Only one at a time |
| When is it a good fit? | Every member is meaningful together | Only one of several alternatives is meaningful at a time |
Comparing struct and union design choices
Practice: Predicting Shared Storage
A union has three members with sizes 3 bytes, 6 bytes, and 4 bytes. First, state how many bytes the union occupies. Then explain what happens to the value held by the 3-byte member after a value is written through the 4-byte member.
Hints
- Apply the rule that the union occupies only as much space as its largest member.
- Think about whether the 3-byte member has its own region or shares the region that the write just overwrote.
Key Takeaways
- A union is a struct in which all members are allocated at the same address, while a struct gives each member its own region.
- A union occupies only as much memory as its largest member, not the sum of its member sizes.
- Because members share storage, a union holds a meaningful value for only one member at a time, and writing through one member replaces what the others would read.
- Choose a struct when every member must hold a value together, and a union when only one of several alternatives is meaningful at any moment.