Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C++

Mục đích của Union trong C/C++

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);