When programming in C or C++, structures and unions allow you to define custom data types to bundle related data together. They seem almost identical on the surface, but have distinct differences under the hood when it comes to memory, values, and efficiency.
In this guide, I‘ll provide a easy-to-understand overview of structures and unions so you can leverage them appropriately in your own code down the road. Along the way, we‘ll look at plenty of examples to solidify the concepts!
Let‘s start by looking at what exactly these data structures are…
An Introduction to Structures and Unions
Structures (also called structs
) are custom data types that allow grouping together different variables into logical units. For example:
struct Car {
string make;
string model;
int year;
//...other car details
};
Here we bundle relevant data about cars into one Car structure type.
Unions also group together different data elements, but with less memory allocated. You‘ll see why soon!
union Data {
int i;
double d;
};
On the whole, structures and unions are very similar constructs – the key differences come down to memory allocation and value handling.
Now let‘s take a deeper look…
Detailed Definition and Syntax Overview
Structures and unions share a similar syntax, but use different key keywords:
Structures:
struct MyStruct {
int member1;
float member2;
//...
};
Unions:
union MyUnion {
char member1;
double member2;
};
Pay attention to whether struct
or union
is used when declaring the type. Also notice that different data types can be members like with structures.
Now that you know how to define them, let‘s move on to where key distinctions emerge…
How Memory Allocation Differs in Structures vs. Unions
The single biggest difference between structures and unions is how they handle memory allocation for their members.
Let‘s take an example:
struct MyStruct {
int num;
char letter;
float decimal;
};
union MyUnion {
int num;
char letter;
float decimal;
};
In MyStruct
, memory would be allocated for each member individually:
int num
: 4 byteschar letter
: 1 bytefloat decimal
: 4 bytes
Total = 9 bytes of memory allocated.
However, in MyUnion
, memory is only allocated for the largest member.
So if a float
takes up 4 bytes (the largest):
Total = 4 bytes of memory allocated.
As you can see, unions minimize memory use by only allocating for the largest member.
But why does this happen and what are the tradeoffs?
Value Storage and Access Differences
Unions can get away with less memory because they only allow access to one member value at a time.
This means unions do NOT support accessing multiple members simultaneously like structures do.
For example:
// Structures
MyStruct s;
s.num = 5;
s.letter = ‘a‘; // Stores values concurrently
// Unions
MyUnion u;
u.num = 3;
u.letter = ‘x‘; // Overwrites previous num value
In structures, each member gets separate storage so values persist across access. With unions, assigning to one member overwrites any previous member values since the same memory space is shared.
You cannot rely on old values remaining when using unions – only structures give you concurrent, persistence access across members.
Impact on Initialization
This difference in concurrency and persistence also impacts initialization:
- Structures can initialize values for all members at time of instantiation
- Unions can only initialize the first member at time of instantiation
For example:
// Structures
struct MyStruct {
int x = 5;
int y = 10; // Initialize multiple members
}
// Unions
union MyUnion {
int a = 5;
int b; // Cannot initialize b and a at same time
};
Unions lose flexibility again due to that single-value constraint.
Performance and Efficiency Tradeoffs
Clearly unions are more limited in some ways. But why use them at all then?
It comes down to efficiency both in terms of memory and performance.
By only storing one value, unions use drastically less memory which leads to:
- Less RAM usage
- Better cache performance in CPU since more data fits
- Less load on memory bus bandwidth
The following shows a memory comparison:
Data Type | Memory Allocation |
---|---|
Struct | 9 bytes |
Equivalent Union | 4 bytes |
That‘s over 50% memory savings with the union!
However, the performance gains require losing concurrent access. So efficiency vs. flexibility is the key tradeoff.
Recommended Use Cases
Based on the differences uncovered, here is when structures and unions tend to be most useful:
Use Structures when:
- You need concurrent access to multiple heterogeneous data elements
- Persistence of all member values is required across access
- Memory use is not highly constrained
For example:
// Group employee data together
struct Employee {
int id;
string name;
float salary;
};
// Concurrent access:
Employee e;
e.id = 5;
e.name = "Bob"; // Id persists
Use Unions when:
- Changing representations of data where only one needs to be active at once
- Extreme memory conservation is required
- You can manage single value constraint properly
For example:
// Store text capitalized or not
union Text {
string upper;
string lower;
};
Text t;
t.lower = "hello"; // Single value
This maximizes memory by only storing one string.
So in summary:
- Structures focus on flexible data persistence
- Unions focus on optimized memory efficiency
Pick the one aligning best with your use case!
Comparing Structures vs. Unions
Here is a helpful summary table outlining the key differences discussed:
Feature | Structures | Unions |
---|---|---|
Definition Statement | struct |
union |
Memory Allocation | Individual per member | Total size of largest member |
Simultaneous Member Access | Yes | No, only one at a time |
Member Value Persistence | Retains values after access | Overwritten after each access |
Initialization Support | All members at once | Only first member |
Use Cases | Flexible concurrent data access | Optimized memory efficiency |
Keep this table handy as a quick guide for choosing between them!
You should now have a solid grasp of structures and unions along with when to use each one. They are powerful constructs that any C or C++ developer should understand.
Both have certain constraints, but applied properly to the right situation can improve your code‘s organization and performance!
Let me know in the comments if you have any other questions. Happy programming!