C C++

Tagged Union in C


Introduction

A tagged union is a programming technique that combines a union with a tag (usually an enumeration) to indicate which union member currently contains valid data.

Since a union can store only one active member at a time, the C language itself does not keep track of which member is currently in use. A tagged union solves this problem by storing an additional value that identifies the active member.

Tagged unions are widely used in compilers, operating systems, embedded systems, interpreters, network protocols, JSON parsers, and many other low-level applications.

Why Do We Need a Tagged Union?

Consider the following union:

Example

        
union Value
{
    int integer;

    float decimal;

    char character;
};
        
    

Although the union can store three different data types, there is no information indicating which member currently contains valid data.

For example:

Example

        
union Value value;

value.integer = 100;
        
    

If another function later receives value, it has no way to determine whether it contains an integer, a floating-point number, or a character.

Warning: A union alone does not record which member is active. Accessing the wrong member may produce incorrect results or undefined behavior.

What Is a Tag?

A tag is an additional variable that records which union member is currently valid.

The tag is usually implemented as an enumeration.

Example

        
enum ValueType
{
    INTEGER,

    FLOAT,

    CHARACTER
};
        
    

The enumeration values identify which union member should be used.

Basic Tagged Union

A tagged union combines an enumeration and a union inside the same structure.

Example

        
struct Value
{
    enum ValueType type;

    union
    {
        int integer;

        float decimal;

        char character;
    };
};
        
    

The type field indicates which union member currently contains valid data.

Using a Tagged Union

Example

        
struct Value value;

value.type = INTEGER;

value.integer = 100;
        
    

Because type is set to INTEGER, other code knows that integer is the active member.

Complete Example

Example

        
#include <stdio.h>

enum ValueType
{
    INTEGER,

    FLOAT,

    CHARACTER
};

struct Value
{
    enum ValueType type;

    union
    {
        int integer;

        float decimal;

        char character;
    };
};

int main(void)
{
    struct Value value;

    value.type = FLOAT;

    value.decimal = 3.14f;

    if (value.type == FLOAT)
    {
        printf("%.2f\n", value.decimal);
    }

    return 0;
}
        
    

Output

        
3.14
        
    

Using switch with Tagged Unions

A switch statement is commonly used to process tagged unions.

Example

        
switch (value.type)
{
    case INTEGER:
        printf("%d\n", value.integer);
        break;

    case FLOAT:
        printf("%f\n", value.decimal);
        break;

    case CHARACTER:
        printf("%c\n", value.character);
        break;
}
        
    

The tag determines which union member should be accessed.

Memory Layout

A tagged union consists of two parts:

  • The tag (usually an enum).
  • The shared-memory union.

A simplified memory layout looks like this:

Example

        
+----------------+
| enum type      |
+----------------+
|                |
|    union       |
|   (shared)     |
|                |
+----------------+
        
    

The structure occupies more memory than the union alone because the tag requires additional storage.

Advantages of Tagged Unions

  • Identifies the active union member.
  • Improves program safety.
  • Makes code easier to understand.
  • Supports multiple data types efficiently.
  • Reduces the chance of reading the wrong union member.

Disadvantages

  • Requires additional memory for the tag.
  • The programmer must update the tag correctly.
  • The compiler does not automatically verify that the tag matches the active member.

Tagged Union vs Ordinary Union

Tagged Union Ordinary Union
Includes an enum tag. No tag.
Knows the active member. Active member is unknown.
Safer. More error-prone.
Slightly larger. Uses less memory.

Real-World Applications

Tagged unions are widely used in:

  • Abstract syntax trees (ASTs).
  • Programming language interpreters.
  • Compilers.
  • JSON parsers.
  • XML parsers.
  • Protocol message handling.
  • Operating systems.
  • Embedded systems.

Tagged Union with typedef

Many projects use typedef to simplify tagged union declarations.

Example

        
typedef enum
{
    INTEGER,

    FLOAT
} ValueType;

typedef struct
{
    ValueType type;

    union
    {
        int integer;

        float decimal;
    };
} Value;
        
    

This produces cleaner declarations throughout the program.

Common Beginner Mistakes

  • Forgetting to update the tag after changing the active member.
  • Reading a member that does not match the current tag.
  • Assuming the compiler validates the tag automatically.
  • Using raw integers instead of an enumeration for the tag.
  • Thinking tagged unions eliminate memory sharing.
Warning: The compiler does not automatically synchronize the tag with the union. If you forget to update the tag, your program may read the wrong member and produce incorrect results.

Best Practices

  • Always use an enumeration as the tag.
  • Update the tag immediately before or after changing the active union member.
  • Use a switch statement to process tagged unions.
  • Keep the tag and the union together in the same structure.
  • Document which tag corresponds to each union member.
Tip: Tagged unions are the closest equivalent to algebraic data types or variant types found in many modern programming languages. They provide both memory efficiency and a reliable way to determine the active value.

Summary

A tagged union combines an enumeration with a union to record which member currently contains valid data. This simple technique makes unions much safer and easier to use while preserving their memory efficiency.

Component Purpose
Enumeration Identifies the active member.
Union Stores one value using shared memory.
Structure Keeps the tag and union together.
Main Benefit Safe handling of multiple data types.
Typical Use Compilers, interpreters, protocols, embedded systems.

Tagged unions are one of the most important design patterns in C programming. They provide a safe and efficient way to represent data that may have different types while minimizing memory usage.