C program to find the size of a union.

A union in C is similar to a structure, but all its members share the same memory location. While a struct allocates separate space for each member, a union allocates space equal to its largest member, and every member overlaps that same block of memory. Only one member holds a valid value at any point in time. This makes unions useful for saving memory and for implementing variant types, but writing one member and reading another is undefined behavior in standard C (with one specific exception for common initial sequences).

The original post used void main() and broken \n escape sequences throughout. This rewrite demonstrates union memory layout, sizeof, and what actually happens when you write one member and read another.

Union vs Struct Memory Layout

Feature struct union
Member storage Each member has its own memory All members share one block
Size Sum of all member sizes (plus padding) Size of the largest member (plus alignment)
Active members All members valid simultaneously Only the last-written member is valid
Typical use Group related data Save memory; implement variant types

C Program: sizeof a Union and Member Aliasing

/* sizeof a union in C: memory layout and member aliasing
 * Compile: gcc -ansi -Wall -Wextra union_demo.c -o union_demo */
#include <stdio.h>

union sample {
    int   m;
    float n;
    char  ch;
};

int main(void)
{
    union sample u;

    /* sizeof(union) = size of the largest member */
    printf("sizeof(int)           = %d bytes\n", (int)sizeof(int));
    printf("sizeof(float)         = %d bytes\n", (int)sizeof(float));
    printf("sizeof(char)          = %d bytes\n", (int)sizeof(char));
    printf("sizeof(union sample)  = %d bytes\n\n", (int)sizeof(u));

    /* All members share the same memory location */
    u.m = 65;
    printf("After u.m = 65:\n");
    printf("  u.m  = %d\n",   u.m);
    printf("  u.ch = '%c'\n", u.ch);  /* 65 is ASCII 'A' */
    printf("  u.n  = %f  (float interpretation of int bits -- undefined)\n\n", u.n);

    u.n = 3.14f;
    printf("After u.n = 3.14:\n");
    printf("  u.n  = %f\n",  u.n);
    printf("  u.m  = %d  (int interpretation of float bits -- undefined)\n", u.m);
    printf("  u.ch = first byte of float -- undefined\n\n");

    u.ch = 'Z';
    printf("After u.ch = 'Z':\n");
    printf("  u.ch = '%c'\n",  u.ch);
    printf("  u.m  = %d  (only lowest byte updated; rest unchanged -- undefined)\n", u.m);

    return 0;
}

How to Compile and Run

gcc -ansi -Wall -Wextra union_demo.c -o union_demo
./union_demo

Sample Output

sizeof(int)           = 4 bytes
sizeof(float)         = 4 bytes
sizeof(char)          = 1 bytes
sizeof(union sample)  = 4 bytes

After u.m = 65:
  u.m  = 65
  u.ch = 'A'
  u.n  = 0.000000  (float interpretation of int bits -- undefined)

After u.n = 3.14:
  u.n  = 3.140000
  u.m  = 1078523331  (int interpretation of float bits -- undefined)
  u.ch = first byte of float -- undefined

After u.ch = 'Z':
  u.ch = 'Z'
  u.m  = 1078523226  (only lowest byte updated; rest unchanged -- undefined)

Code Explanation

  • sizeof(union sample) = 4 bytes — the union contains int (4 bytes), float (4 bytes), and char (1 byte). The compiler allocates space equal to the largest member: 4 bytes. All three members start at the same address and share those 4 bytes. A struct with the same members would be at least 9 bytes (4+4+1, possibly more due to alignment padding).
  • u.ch = ‘A’ after u.m = 65 — 65 in decimal is 0x41 in hex, which is the ASCII code for ‘A’. The char member reads the lowest byte of the shared 4-byte block. On a little-endian system (x86), that is the byte where the integer value 65 is stored, so u.ch correctly shows ‘A’. This particular read happens to be well-defined because reading the integer representation via char is allowed in C.
  • u.n = 0.000000 after u.m = 65 — 65 stored as an IEEE 754 float (0x00000041) is a tiny denormalized number that prints as 0.000000 at 6-decimal-place precision. Reading a float after storing an int is technically undefined behavior in C89/C90 (the standard only allows reading the last-written member), so this output is implementation-specific.
  • u.m = 1078523331 after u.n = 3.14 — the 32-bit IEEE 754 bit pattern for 3.14f is 0x4048F5C3 = 1,078,523,331 in decimal. The float’s bits are being reinterpreted as an int. Again, undefined behavior — but it shows the raw bit pattern.
  • Union size and alignment — the union’s size must be a multiple of its alignment requirement. If the largest member is a double (8 bytes, aligned to 8), the union will be sized and aligned to 8 bytes, even if the other members are smaller. Alignment padding can make unions larger than just the largest member.

Practical Uses of Unions

  • Tagged union (variant type) — combine a union with a tag field in a struct: struct { int type; union { int i; float f; char *s; } val; }. The tag says which union member is currently active. This is how dynamic languages implement variable types.
  • Network protocol parsing — overlay a union over raw bytes to access different fields of a packet without copying. Note: this is technically undefined behavior in strict C, but compilers (especially GCC) support it as an extension for this exact use case.
  • Saving memory in arrays — an array of tagged unions uses exactly as much memory as the largest variant, unlike an array of structs where each slot has all possible fields regardless of which is used.
  • Type punning via memcpy — the C99+ standard-compliant way to convert an int’s bit pattern to float is: float f; int i = 0x3F800000; memcpy(&f, &i, sizeof(f));. This achieves the same bit-level reinterpretation as a union without undefined behavior.

What This Program Teaches

  • All members overlap at address 0 of the union — you can verify this with: printf("%p %p %p\n", (void*)&u.m, (void*)&u.n, (void*)&u.ch); — all three print the same address.
  • sizeof(union) is not the sum of members — a common exam question. For union { int; float; char; }, sizeof is 4 (largest member), not 4+4+1=9.
  • Only the last-written member is valid — the C standard says reading a union member that is not the currently active member is undefined behavior (with an exception for inspecting the representation via unsigned char members).

Related Programs

Recommended book:
The C Programming Language — Kernighan & Ritchie (India) |
(US)
 | 
C Programming: A Modern Approach — K.N. King (India) |
(US)

Practice what you learned: C Aptitude Questions — or try our C Programming Quiz App on Android.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>