Union là kiểu dữ liệu do người dùng định nghĩa, cho phép nhiều member chia sẻ cùng một vùng nhớ. Kích thước union = kích thước member lớn nhất.
Cú pháp
union TenUnion {
kiểu thành_viên1;
kiểu thành_viên2;
...
} biến_union;
Ví dụ cơ bản
#include <stdio.h>
#include <string.h>
union Data {
int i;
float f;
} data, data1;
int main() {
printf("Kích thước union: %zu %zu\n", sizeof(data), sizeof(data1));
// Kết quả: 4 4 (max của int và float)
return 0;
}
Kết quả
Kích thước union: 4 4
Tại sao dùng Union?
1. Tiết kiệm bộ nhớ (Embedded systems)
// Chỉ cần lưu một trong các trạng thái tại một thời điểm
union SensorData {
int temperature;
float pressure;
double humidity;
}; // Size = 8 bytes (thay vì 4+4+8=16)
2. Type Punning (Xem dữ liệu dưới góc độ khác)
union FloatInt {
float f;
uint32_t bits;
};
FloatInt converter;
converter.f = 3.14f;
printf("Float bits: 0x%08X\n", converter.bits); // 0x4048F5C3
3. Protocol/Message với nhiều loại payload
struct Message {
int type;
union {
struct { int x, y; } mouse;
struct { char key; } keyboard;
struct { int id; char data[64]; } network;
} payload;
};
4. Variant type (trước C++17)
union Value {
int i;
double d;
char* s;
};
struct TaggedValue {
enum { INT, DOUBLE, STRING } tag;
Value value;
};
Lưu ý quan trọng
- Chỉ member cuối cùng được ghi mới hợp lệ - đọc member khác là UB (trừ common initial sequence)
- Không thể dùng union cho kiểu có constructor/destructor non-trivial (C++03). C++11 cho phép nhưng cần placement new
- C++17: Thay thế bằng
std::variant(an toàn kiểu, visitor pattern) - Alignment: union có alignment = max alignment của các member
C++17 std::variant - Thay thế hiện đại
#include <variant>
#include <iostream>
std::variant<int, float, std::string> v = 42;
v = 3.14f;
v = "hello";
// Truy cập an toàn
if (auto* p = std::get_if<int>(&v)) {
cout << "int: " << *p;
}
std::visit([](auto&& arg) { cout << arg; }, v);