C C++

Memory Layout Union in C


Introduction

One of the defining characteristics of a union is its memory layout. Unlike a structure, where each member occupies its own storage, all members of a union share the same memory location.

Understanding how memory is organized inside a union is essential for writing efficient C programs, especially in embedded systems, operating systems, network programming, and other low-level applications.

This article explains how union memory is allocated, how members overlap, and how the size of a union is determined.

How Memory Is Allocated in a Union

When a union is created, the compiler allocates a single block of memory that is large enough to store its largest member.

Every member begins at the same memory address and shares this storage.

Syntax

        
union Data
{
    int number;

    float decimal;

    char character;
};
        
    

Although the union contains three members, only one memory block is allocated.

Visualizing the Memory Layout

Suppose the implementation uses the following sizes:

Type Size
char 1 byte
int 4 bytes
float 4 bytes

The memory layout of the union can be represented as:

Example

        
+-----------------------+
| Byte 0               |
| Byte 1               |
| Byte 2               |
| Byte 3               |
+-----------------------+

number     ----+
decimal    ----+--> Same memory
character  ----+
        
    

All three members start at the same address and occupy the same memory region.

Every Member Has the Same Starting Address

Since all members share memory, their addresses are identical.

Example

        
#include <stdio.h>

union Data
{
    int number;

    float decimal;

    char character;
};

int main(void)
{
    union Data value;

    printf("%p\n", (void *)&value.number);
    printf("%p\n", (void *)&value.decimal);
    printf("%p\n", (void *)&value.character);

    return 0;
}
        
    

Typical output:

Output

        
0x7ffd...
0x7ffd...
0x7ffd...
        
    

Although the exact address varies, all members have the same starting location.

Writing to One Member Affects All Others

Because every member occupies the same storage, writing to one member changes the underlying bytes used by every other member.

Example

        
union Data
{
    int number;

    float decimal;
};

union Data value;

value.number = 100;

value.decimal = 3.14f;
        
    

After assigning decimal, the bytes that previously represented number have been overwritten.

Warning: Only one union member should normally be considered active at a time. Writing to one member generally invalidates the value stored in the others.

Union Size

The size of a union is determined by its largest member, plus any alignment required by the implementation.

Example

        
#include <stdio.h>

union Data
{
    char c;

    int number;

    double decimal;
};

int main(void)
{
    printf("%zu\n", sizeof(union Data));

    return 0;
}
        
    

The exact size depends on the platform, but it will always be at least large enough to hold the largest member.

Example of Size Calculation

Assume the following implementation:

Member Size
char 1 byte
int 4 bytes
double 8 bytes

The union size is typically:

Example

        
sizeof(union Data) == 8
        
    

The smaller members reuse the same eight-byte storage allocated for the largest member.

Alignment and Padding

Like structures, unions may contain padding to satisfy alignment requirements.

For example, a union containing a double usually requires alignment suitable for double, even if smaller members need less alignment.

Note: The exact alignment and padding are implementation-defined and may differ between compilers and hardware architectures.

Comparing Union and Structure Memory Layout

Union Structure
Members share memory. Members have separate memory.
Single starting address. Different member addresses.
Size equals the largest member (plus alignment). Size is approximately the sum of all members (plus padding).
One active member. All members may contain values simultaneously.

Inspecting Memory with sizeof

The sizeof operator can be used to determine the amount of memory occupied by a union.

Example

        
printf("%zu\n", sizeof(union Data));
        
    

This is useful when designing memory-efficient data structures.

Why Shared Memory Is Useful

Sharing memory makes unions valuable in situations where only one representation of data is needed at a time.

Typical applications include:

  • Embedded systems.
  • Hardware register mapping.
  • Communication protocols.
  • Binary file formats.
  • Tagged unions (variant types).

Common Beginner Mistakes

  • Thinking every member has separate storage.
  • Assuming multiple members can safely hold independent values simultaneously.
  • Expecting the union size to equal the sum of member sizes.
  • Ignoring alignment requirements.
  • Reading a different member after writing another without understanding the consequences.
Warning: Although different members share the same memory, interpreting the stored bytes through a different member may produce implementation-defined or undefined behavior depending on the situation. Always understand the rules before using unions for type reinterpretation.

Best Practices

  • Use unions only when memory sharing is intentional.
  • Keep track of which member is currently active.
  • Use an accompanying enum to identify the active member.
  • Use sizeof rather than assuming memory sizes.
  • Be aware that alignment and padding may vary across platforms.
Tip: A good mental model is to imagine a union as a single storage box with multiple labels. Each label represents a different interpretation of the same bytes rather than a separate piece of memory.

Summary

The memory layout of a union is based on a single shared memory block that is large enough for its largest member. Every member starts at the same address, and only one member should normally be considered active at a time.

Property Union
Memory Allocation Single shared block
Member Addresses All members start at the same address
Union Size Largest member (plus alignment)
Active Member One at a time
Main Benefit Memory efficiency

Understanding the memory layout of unions is fundamental to systems programming in C. It enables you to write memory-efficient programs while safely working with multiple representations of the same data.