Question
In C, what is a good way to understand the difference between a struct and a union?
I understand that a struct stores enough memory for all of its members, while a union uses only enough memory for its largest member. Beyond that memory layout difference, are there any other important differences, such as operating system-level behavior?
For example, how should I think about these two declarations?
struct ExampleStruct {
int id;
float price;
char code;
};
union ExampleUnion {
int id;
float price;
char code;
};
Short Answer
By the end of this page, you will understand how struct and union differ in C, especially in memory layout, data access, and practical use. You will also learn that this is mainly a language and memory-model concept, not an operating system feature.
Concept
A struct and a union are both user-defined types in C, but they represent data in very different ways.
struct
A struct gives each member its own storage. All fields can hold valid values at the same time.
struct Point {
int x;
int y;
};
If you set x and y, both values are stored independently.
union
A union makes all members share the same memory location. Only one member's value is meaningfully stored at a time.
union Number {
int i;
float f;
};
If you write to i and then write to f, the f write reuses the same bytes and overwrites the previous contents.
Mental Model
Think of a struct as a desk with separate labeled drawers:
- one drawer for
id - one drawer for
price - one drawer for
code
Each member has its own space, so all values can exist together.
Think of a union as a single drawer with several labels stuck on it:
idpricecode
There is still only one drawer. The labels are different ways to interpret the same space. If you put something in as id and later put something in as price, the new value replaces the old bytes.
So:
struct= many storage locations grouped togetherunion= one storage location viewed in different ways
Syntax and Examples
Basic syntax
struct Person {
int age;
char initial;
};
union Value {
int i;
float f;
char c;
};
Example: struct
#include <stdio.h>
struct Person {
int age;
char initial;
};
int main(void) {
struct Person p;
p.age = 25;
p.initial = 'A';
printf("age = %d\n", p.age);
printf("initial = %c\n", p.initial);
return 0;
}
Here both fields keep their values because each member has separate storage.
Example: union
Step by Step Execution
Consider this union example:
#include <stdio.h>
union Data {
int i;
char c;
};
int main(void) {
union Data d;
d.i = 65;
printf("d.i = %d\n", d.i);
d.c = 'B';
printf("d.c = %c\n", d.c);
return 0;
}
Step by step
-
union Data d;- Memory is reserved for one
union Datavariable. - Its size is enough for the largest member.
- Memory is reserved for one
-
d.i = 65;- The shared memory is filled with the integer representation of
65. - At this point,
iis the active member.
- The shared memory is filled with the integer representation of
Real World Use Cases
When struct is used
struct is used far more often than union in everyday C programming.
Common uses:
- storing records such as users, points, products, or configuration data
- grouping related fields into one object
- representing packets, headers, or state objects
- passing multiple related values to functions
Example:
struct User {
int id;
char role;
float rating;
};
A user has all of these properties at the same time, so struct is the correct choice.
When union is used
union is useful when a value can be one of several types, but never all at once.
Common uses:
- memory-constrained systems
- parsers handling different token value types
- message payloads where only one payload format is active
- tagged data types combined with an enum
Example:
{
TYPE_INT,
TYPE_FLOAT,
TYPE_CHAR
};
i;
f;
c;
} data;
};
Real Codebase Usage
In real projects, developers usually use union together with a tag that tells the program which member is currently valid.
Tagged union pattern
enum EventType {
EVENT_KEY,
EVENT_MOUSE
};
struct Event {
enum EventType type;
union {
int key_code;
struct {
int x;
int y;
} mouse;
} data;
};
This is common in:
- event systems
- compilers and interpreters
- protocol handling
- embedded firmware
Why the tag matters
Without a tag, code can easily read the wrong union member.
struct usage patterns in real code
Developers use struct for:
- configuration objects
- return values with multiple fields
- state containers
- linked list and tree nodes
- API request and response models
Guarding access to unions
A common pattern is:
Common Mistakes
1. Thinking a union stores all members at once
Broken assumption:
union Data {
int i;
float f;
};
union Data d;
d.i = 10;
d.f = 2.5f;
printf("%d\n", d.i); // Not a safe way to expect the old int value
Why it is wrong:
- assigning
d.foverwrites the shared memory d.iis no longer the active value
2. Using a union when a struct is needed
Broken design:
union Person {
int age;
char initial;
};
If a person needs both age and initial, use a struct, not a union.
3. Ignoring padding and alignment
Beginners often assume sizes are just the sum of member sizes.
Comparisons
| Feature | struct | union |
|---|---|---|
| Memory for members | Separate memory for each member | Shared memory for all members |
| Total size | Usually enough for all members plus padding | Enough for largest member plus alignment |
| Can all members hold values at once? | Yes | No, only one meaningful active member at a time |
| Typical use | Records and grouped data | Variant data and memory saving |
| Safer for beginners | Yes | Less so |
| Common in application code | Very common | More specialized |
struct vs union in one sentence
Cheat Sheet
struct S {
int a;
float b;
};
union U {
int a;
float b;
};
struct: each member has its own storageunion: all members share the same storagestructsize: enough for all members + paddingunionsize: enough for largest member + alignmentstruct: all fields can be used togetherunion: only one member should be treated as active- No special OS-level difference in normal C usage
- Layout details depend on compiler, target, and alignment rules
Good rule of thumb
- Need multiple fields at once? Use
struct. - Need one value that may take different forms? Use
union.
Safer union pattern
enum Kind { INT_KIND, FLOAT_KIND };
{
i;
f;
} data;
};
FAQ
Is a union just a smaller struct?
No. A union is not just a space-optimized struct. Its members share the same memory, which changes how values are stored and read.
When should I use a struct instead of a union?
Use a struct when all fields are part of the object at the same time, such as a user with an id, name, and age.
When is a union useful in C?
A union is useful when a value can be one of several types, such as a token in a parser or an event payload in a system.
Does the operating system treat structs and unions differently?
Usually no. This is mainly a C language and compiler memory layout issue, not an OS-level distinction.
Why is a union often combined with an enum?
The enum acts as a tag so the program knows which union member currently contains valid data.
Can a union and struct have unexpected sizes?
Yes. Alignment and padding can change sizes, especially for structs. Always use sizeof instead of guessing.
Is reading one union member after writing another allowed?
It may compile, but it can be tricky and is often not the right design for beginners. Use a tagged union pattern when possible.
Mini Project
Description
Build a small C program that stores different kinds of values using a tagged union. This demonstrates the practical difference between struct and union: the struct holds the type tag and the union holds one active value.
Goal
Create a program that can store and print either an integer, a float, or a character safely using an enum and a union.
Requirements
- Define an
enumto represent the active value type. - Define a
structthat contains the enum tag and a union of possible values. - Create at least three example values: one integer, one float, and one character.
- Write a function that prints the stored value based on the tag.
- Compile and run the program to verify that each value is printed correctly.
Keep learning
Related questions
Array-to-Pointer Conversion in C and C++ Explained
Learn what array-to-pointer conversion means in C and C++, how array decay works, and how it differs from a pointer to an array.
Building More Fault-Tolerant Embedded C++ Applications for Radiation-Prone ARM Systems
Learn practical C++ and compile-time techniques to reduce soft-error damage in embedded ARM systems exposed to radiation.
C Pointer to Array vs Array of Pointers: How to Read Complex Declarations
Learn the difference between pointer-to-array and array-of-pointers in C, plus a simple rule for reading complex declarations correctly.