Unions in C
A union in C is a special data type that allows you to store different data types in the same memory location. Think of it like a shared storage box where you can put different types of items, but only one item at a time!
What Makes Unions Special?
Unlike structures where each member has its own memory space, all members of a union share the same memory location. This means:
- Only one member can hold a value at any given time
- The size of a union is equal to the size of its largest member
- Unions help save memory when you need to store different types of data, but not simultaneously
Declaring a Union
The syntax for declaring a union is similar to structures, but uses the union keyword:
union DataType {
int integer_val;
float float_val;
char char_val;
};
Creating Union Variables
You can create union variables in several ways:
// Method 1: Declare union first, then create variables
union DataType data1, data2;
// Method 2: Declare and create variables together
union DataType {
int integer_val;
float float_val;
char char_val;
} data1, data2;
// Method 3: Using typedef
typedef union {
int integer_val;
float float_val;
char char_val;
} DataType;
DataType data1, data2;
Accessing Union Members
Use the dot operator (.) to access union members:
#include <stdio.h>
union Number {
int i;
float f;
char c;
};
int main() {
union Number num;
// Store an integer
num.i = 42;
printf("Integer: %d\n", num.i);
// Store a float (overwrites the integer)
num.f = 3.14;
printf("Float: %.2f\n", num.f);
// Store a character (overwrites the float)
num.c = 'A';
printf("Character: %c\n", num.c);
return 0;
}
Memory Layout Example
Let's see how memory is shared in unions:
#include <stdio.h>
union Example {
int i; // 4 bytes
float f; // 4 bytes
char c; // 1 byte
};
int main() {
union Example ex;
printf("Size of union: %lu bytes\n", sizeof(ex));
printf("Address of i: %p\n", &ex.i);
printf("Address of f: %p\n", &ex.f);
printf("Address of c: %p\n", &ex.c);
return 0;
}
Output:
Size of union: 4 bytes
Address of i: 0x7fff5fbff6ac
Address of f: 0x7fff5fbff6ac
Address of c: 0x7fff5fbff6ac
Notice how all members have the same memory address!
Practical Use Cases
1. Type Conversion
union FloatBytes {
float f;
unsigned char bytes[4];
};
int main() {
union FloatBytes fb;
fb.f = 3.14159;
printf("Float: %.5f\n", fb.f);
printf("Bytes: ");
for(int i = 0; i < 4; i++) {
printf("%02X ", fb.bytes[i]);
}
printf("\n");
return 0;
}
2. Variant Data Types
union Variant {
int int_val;
double double_val;
char string_val[20];
};
struct Data {
int type; // 1=int, 2=double, 3=string
union Variant value;
};
Important Points to Remember
| Aspect | Union | Structure |
|---|---|---|
| Memory | Shared among all members | Separate for each member |
| Size | Size of largest member | Sum of all members |
| Access | One member at a time | All members simultaneously |
| Use Case | Save memory, variant types | Group related data |
Common Pitfalls
⚠️ Warning: Accessing a union member that wasn't the last one assigned can lead to unexpected results:
union Test {
int i;
float f;
};
int main() {
union Test t;
t.i = 42;
printf("Float value: %.2f\n", t.f); // Undefined behavior!
return 0;
}
Unions are powerful tools for memory optimization and low-level programming, but they require careful handling to avoid data corruption!