Shiklo Tools
PDF40
Image20
Calculators & Converters25
Text & Writing13
Developer26
Video14
Audio14
Document14
Data & Spreadsheet12
Web & SEO9
OCR & Scanning5
Archive & File12
Security & Privacy23
Health & Medical29
QR & Barcode5

C Unions

A union looks like a structure, but all its members share the same memory. Only one member holds a meaningful value at a time. Unions save memory when a value can be one of several types, but never two at once.

Structure and union compared

#include <stdio.h>

struct S { int i; double d; char c; };
union  U { int i; double d; char c; };

int main(void) {
    printf("struct: %zu bytes\n", sizeof(struct S));
    printf("union:  %zu bytes\n", sizeof(union U));
    return 0;
}
Output
struct: 24 bytes
union:  8 bytes

The structure has room for all three members (plus some padding the compiler adds for alignment). The union is only as big as its largest member, the double.

One value at a time

Writing one member of a union overwrites the others. Read the member you wrote last:

#include <stdio.h>

union Value {
    int i;
    float f;
};

int main(void) {
    union Value v;
    v.i = 42;
    printf("as int: %d\n", v.i);
    v.f = 3.5f;          // now the int is overwritten
    printf("as float: %.1f\n", v.f);
    return 0;
}
Output
as int: 42
as float: 3.5

Tagged unions

A union does not remember which member is in use, so programs usually pair it with an enum "tag" inside a structure. This is a tagged union, a common pattern for values that can be of several kinds:

#include <stdio.h>

typedef enum { NUMBER, TEXT } Kind;

typedef struct {
    Kind kind;
    union {
        double number;
        const char *text;
    } as;
} Item;

void printItem(Item it) {
    if (it.kind == NUMBER) printf("number: %.2f\n", it.as.number);
    else printf("text: %s\n", it.as.text);
}

int main(void) {
    Item a = {NUMBER, {.number = 2.5}};
    Item b = {TEXT, {.text = "hello"}};
    printItem(a);
    printItem(b);
    return 0;
}
Output
number: 2.50
text: hello

When to use unions

Unions are a specialised tool: message formats where each message type has different fields, interpreters that store values of several types, and code close to hardware. In everyday programs a structure is usually the clearer choice. Reading a member other than the one last written reinterprets the same bytes as another type (the bytes of a float read as an int, for example), which is almost never what a program wants, so always keep track of which member is active.

Practice exercises

  1. Print the size of a union holding a char, a short and a long long.
  2. Add a third kind, FLAG holding an int, to the tagged Item and print one.
  3. Make an array of Item values of mixed kinds and print them all with a loop.