Concepts / Choosing Between Structs and Unions

Choosing Between Structs and Unions

A union is a struct in which all members are allocated at the same address.

  • Programming

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
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

Definition

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.

nameown regionnameshared regionvalueshared regionvalueown region
In a struct, each member has its own region, so both members exist side by side. In a union, both members are allocated at the same shared region.

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.

shared regionholds 5 as countshared regionholds text as namewrite through name
Before the write, the shared region holds a number stored through the count member. After the write through the name member, the same region holds text, and the count value is no longer meaningful.

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
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:

Rule

Worked example

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?

  1. 1
    List the member sizes

    The sizes are 4, 8, and 2 bytes.

  2. 2
    Find the largest member

    The largest is the 8-byte member.

  3. 3
    Ignore 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.

  4. 4
    State 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.

Result

The union occupies 8 bytes.

4-byte memberstarts at shared start8-byte memberstarts at shared start2-byte memberstarts at shared startunion size8 byteslargest member sets size
Members of 4, 8, and 2 bytes all start at the same point. The shared region spans the largest member, so the union is 8 bytes rather than 14.

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 like

    For members of 4, 8, and 2 bytes, computing 4 + 8 + 2 = 14 bytes.

    Why it fails

    Members of a union share storage rather than receiving separate regions, so their sizes are not summed.

    Do this instead

    Find 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 like

    Writing a number through one member and then a text value through another, and assuming the number is still readable.

    Why it fails

    Every member occupies the same region, so storing through one member replaces what was in the shared region.

    Do this instead

    Treat 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 like

    Writing through the name member and then reading the value member as if it were a valid number.

    Why it fails

    The bits in the shared region are generally not the value you expect when read through a different member.

    Do this instead

    Read 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.

QuestionStructUnion
Where are the members placed?Each member has its own regionAll members are allocated at the same address
How much space is occupied?Room for all members togetherOnly as much as the largest member
How many members hold values at once?All of themOnly one at a time
When is it a good fit?Every member is meaningful togetherOnly one of several alternatives is meaningful at a time

Comparing struct and union design choices

Practice: Predicting Shared Storage

MEDIUM

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.

More concepts starting with C