union trong C/C++
union
là kiểu dữ liệu người dùng tự định nghĩa, khác biệt với struct là các thuộc tính của union sử dụng chung vùng nhớ.
Sử dụng union
union có cách định nghĩa như struct:
union UnionName { type attribute1; type attribute2; type attribute3; .... ..........; };
Ví dụ về cú pháp khai báo và sử dụng
// Khai báo 1 union union Hardware { float _cpu; short _ram; int _ssd; }; // Sử dụng union int main() { Hardware h; h._cpu = 3.2f; h._ram = 256; h._ssd = 1024; return 0; }
Khi được định nghĩa như trên, union Hardware
có kích thước của thuộc tính có kích thước lớn nhất, trong trường hợp này float
hoặc int
là 4 bytes nên union này có kích thước là 4 bytes.
Với cách sử dụng (dùng chung vùng nhớ) như trên, 3 thuộc tính _cpu
, _ram
, _ssd
ghi đè lên nhau trong quá trình sử dụng.
Các trường hợp sử dụng union
Cần tiết kiệm vùng nhớ
Trong cùng 1 tầm vực, 1 biến được cấp phát tĩnh được khởi tạo khi bắt đầu vào hàm và hủy khi kết thúc hàm.
void func() { // (1) Đoạn code cần dùng biến ram int ram = 2048; // MB printf("RAM: %d", ram); // (2) Đoạn code không cần dùng biến ram, nhưng cần dùng biến hdd int ssd = 1024; // GB printf("SSD: %d", ssd); }
Với code trên, cần 8 bytes dành cho 2 biến là ram
và hdd
, giả sử cho đến khi sử dụng ssd
thì biến ram
không cần dùng nữa, vậy có thể sử dụng luôn biến ram
để lưu trữ thông tin ssd
? Về mặc lý thuyết có thể sử dụng, nhưng thực tế sẽ tự gây khó khăn khi sử dụng biến không rõ ngữ nghĩa và dẫn đến lỗi tiềm ẩn.
Để giải quyết vấn đề ngữ nghĩa và tiết kiệm bộ nhớ trong trường hợp này, có thể sử dụng union
.
// Khai báo 1 union union Hardware { short _ram; int _ssd; }; void func() { Hardware hw; // (1) Đoạn code cần dùng ram hw.ram = 2048; // MB printf("RAM: %d", hw.ram); // (2) Đoạn code không cần dùng ram, nhưng cần dùng hdd hw.ssd = 1024; // GB printf("SSD: %d", hw.ssd); }
Tiết kiệm vùng nhớ sẽ hữu ích với các ứng dụng có bộ nhớ nhỏ như trong lập trình nhúng, ví dụ như Arduino Uno R3 dùng ATmega328P, dung lượng bộ nhớ chỉ khoảng 2KB (2048 bytes).
Cần tổ chức chương trình
Xem xét đoạn codes bên dưới
union Vector4 { struct { float r, g, b, a; }; struct { float x, y, z, w; }; struct { float s, t, p, q; }; float color[4]; float position[4]; float textcoord[4]; }; void rgba_vn() { Vector4 logo_color; logo_color.r = 255.0f; logo_color.color[0] = 240.0f; Vector4 monster_position; monster_position.x = 100.0f; // ... }
Với cách sử dụng union
như trên có thể sử dụng 1 cấu trúc dữ liệu thống nhất là Vector4
cho 3 trường hợp: màu sắc (color[4]
), tạo độ (position[4]
) và bảng ánh xạ màu sắc (textcoord[4]
) hoặc có thể sử dụng dưới dạng mảng chỉ số khi cần thiết.