Table of Contents
What Is a Union in C?
A union in C is a user-defined data type that allows multiple variables to share the same memory location, unlike a struct where each member has its own storage, a union stores only one member at a time.
Syntax
union Data {
int i;
float f;
char c;
};Here, all three members (i, f, c) share the same memory.
Declaring a Union
Declaring a union is almost identical to declaring a structure, but you use the union keyword. The members are accessed by using the dot(.) operator.
Syntax:
union UnionName {
dataType member1;
dataType member2;
// ...
}Consider the code below
#include
#include
union Data {
int i;
float f;
char str[20];
};
int main() {
union Data d1;
// Step 1: Use Integer
d1.i = 10;
printf("Integer: %d\n", d1.i); // Integer: 10
// Step 2: Use Float (Overwrites Integer)
d1.f = 220.5;
printf("Float: %.2f\n", d1.f); // Float: 220.50
// Step 3: Use String (Overwrites Float)
strcpy(d1.str, "C Programming");
printf("String: %s\n", d1.str); // String: C Programming
return 0;
}
Memory Layout in C Unions
In a union, all members use the same memory block. The union allocates memory equal to the size of its largest member. Unlike a structure (which places variables side-by-side), a union stacks them all on top of each other at the exact same memory address. This means you can only use one member at a time. If you change one member you overwrite the others.

#include
union Data {
int i;
float f;
};
int main() {
union Data data;
// 1. We use the Integer member
data.i = 10;
printf("Step 1 - Integer: %d\n", data.i);
// 2. We use the Float member
data.f = 220.5;
printf("Step 2 - Float: %.2f\n", data.f);
// Since we wrote to 'f', the memory for 'i' was overwritten.
printf("Step 3 - Integer (after float update): %d\n", data.i);
return 0;
}
// Step 1 - Integer: 10
// Step 2 - Float: 220.50
// Step 3 - Integer (after float update): 1130135552
Explanation
- Step 1: You wrote 10 into the memory box. The box holds integer data.
- Step 2: You wrote 220.5 into the same memory box. The integer 10 is wiped out.
- Step 3: You asked for the integer data.i. The computer looked at the box, saw the binary code for 220.5, but tried to read it as an integer. This resulted in the garbage number 1130135552.
Nested Unions
A Nested Union is when you put a union inside a structure (or inside another union). It is used when a variable needs to store different types of data depending on the situation, often paired with a “tag” or “flag” variable to remember which type is currently being stored.
#include
union NestedUnion {
int i;
// Inner Union
union {
float f;
char c;
} internal;
};
int main() {
union NestedUnion u;
// 1. Access the outer integer
u.i = 100;
printf("Outer Integer: %d\n", u.i);
// 2. Access the inner float
// This overwrites u.i because they ALL share the same memory
u.internal.f = 3.14;
printf("Inner Float: %.2f\n", u.internal.f);
// 3. Access the inner char
// Note: This overwrites u.internal.f (and u.i)
u.internal.c = 'A';
printf("Inner Char: %c\n", u.internal.c);
return 0;
}
// Outer Integer: 100
// Inner Float: 3.14
// Inner Char: A
Struct with Union
Unions can also be used with structures.
Example: A “Student ID” System . Imagine a system where a student can be identified either by a numeric ID or by their name (but not both).
#include
#include
struct Student {
int type; // 0 = ID Number, 1 = Name
// Union inside the Struct
union {
int id_num;
char name[20];
} info;
};
int main() {
struct Student s1;
// SCENARIO 1: We want to identify by ID Number
s1.type = 0; // Set flag to 0
s1.info.id_num = 101; // Assign ID
// Check the flag before printing
if(s1.type == 0) {
printf("Student Identified by ID: %d\n", s1.info.id_num);
}
// SCENARIO 2: We want to identify by Name
// This overwrites the ID number in memory
s1.type = 1; // Set flag to 1
strcpy(s1.info.name, "Ravi"); // Assign Name
// Check the flag before printing
if(s1.type == 1) {
printf("Student Identified by Name: %s\n", s1.info.name);
}
return 0;
}
// Student Identified by ID: 101
// Student Identified by Name: Ravi
Why use a Struct outside?
We need the struct wrapper so we can store the int type permanently. If type were inside the union, it would get overwritten every time we added a name or ID!
Structure vs Union
| Feature | Structure | Union |
|---|---|---|
| Keyword | struct | union |
| Memory Allocation | Each member gets its own separate memory. | All members share the same memory location. |
| Access | You can access all members at the same time. | You can access only one member at a time. |
| Value Altering | Changing one member does not affect others. | Changing one member overwrites/corrupts the others. |
| Total Size | Equal to the sum of the size of all members (plus padding). | Equal to the size of the largest member. |
| Initialization | All members can be initialized at once. | Only the first member can be initialized. |
Applications
Memory Optimization: Used in embedded systems and low-memory environments to save RAM.
Operating Systems: Used in process control blocks, file systems and device drivers.
Compilers & Interpreters: Unions store different token types, syntax tree nodes and symbol table entries.
Network Protocols: Used to interpret packet headers and binary data formats efficiently.
Hardware & Device Drivers: Used to access hardware registers where the same memory represents different data formats.
Frequently Asked Questions
1. How to initialize a union?
union Data d1 = { .member_name = value };
union Data {
int i;
float f;
};
int main() {
// We explicitly say we want to initialize 'f'
union Data d1 = { .f = 3.14 };
printf("Float: %.2f", d1.f);
return 0;
}
2) What is the difference between structure and union?
A structure allocates separate memory for each member, whereas a union shares the same memory among all members, using space equal to its largest member.
3) Can a union store multiple values at the same time?
No.
A union can store only one value at a time because all members share the same memory location.
4) How does a union know which member is active?
It does not track it automatically. The programmer must track the active member manually—usually using an enum or a flag variable.