Struct and Union
Chắc chắn rồi! Dưới đây là bảng so sánh chi tiết giữa struct và union trong lập trình nhúng (embedded C), rất quan trọng khi làm việc với các bản đồ thanh ghi, giao tiếp ngoại vi, truy cập bit và tối ưu bộ nhớ.
🧠 1. Định nghĩa
| Đặc điểm | struct | union |
| Khái niệm | Tập hợp các biến (gọi là thành viên) được gom lại dưới một tên chung. Các thành viên có bộ nhớ riêng. | Tập hợp các biến nhưng dùng chung vùng nhớ, tức là chỉ một thành viên có giá trị tại một thời điểm. |
| Cú pháp | struct MyStruct { int a; char b; }; | union MyUnion { int a; char b; }; |
🗂 2. Cách sử dụng bộ nhớ
🔸 struct
Mỗi trường (field) được lưu ở một vị trí bộ nhớ riêng biệt.
Tổng kích thước = tổng các kích thước thành viên (có thể thêm padding).
Ví dụ:
struct MyStruct {
int a; // 4 bytes
char b; // 1 byte (+3 byte padding để giữ alignment)
float c; // 4 bytes
};
// Tổng kích thước: 12 bytes (hoặc 8/16 tùy kiến trúc và alignment)
🔹 union
Tất cả thành viên dùng chung 1 vùng nhớ, kích thước của
unionlà kích thước của thành viên lớn nhất.Ghi vào một trường sẽ ghi đè giá trị trường khác.
union MyUnion {
int a; // 4 bytes
char b; // 1 byte
float c; // 4 bytes
};
// Tổng kích thước: 4 bytes
🧰 3. Ứng dụng trong lập trình nhúng
| Lĩnh vực | struct | union |
| Mapping thanh ghi (register) | ✅ Dùng để biểu diễn layout chi tiết của thanh ghi (gồm nhiều bit/field) | ✅ Dùng khi cần truy cập nhiều kiểu dữ liệu hoặc nhiều cách biểu diễn cùng 1 vùng nhớ |
| Truy cập bit cụ thể (bit-field) | ✅ Phối hợp với bit-field để định nghĩa từng bit trong thanh ghi | ✅ Phối hợp với struct để vừa truy cập toàn thanh ghi, vừa truy cập từng bit |
| Giao tiếp truyền dữ liệu (I2C/SPI/UART) | ✅ Dùng để đóng gói khung dữ liệu (packet) | ✅ Dùng khi cần ánh xạ cùng 1 vùng dữ liệu vào nhiều dạng khác nhau |
| Tối ưu RAM/Flash | ❌ Không hiệu quả vì mỗi field chiếm chỗ riêng | ✅ Rất hữu ích khi làm việc với RAM hạn chế |
| Protocol decoding (CAN, Modbus, BLE...) | ✅ Định nghĩa khung dữ liệu chi tiết | ✅ Truy cập dạng raw byte hoặc dạng struct tùy lúc |
🧪 4. Ví dụ thực tế
union kết hợp struct để map thanh ghi:
typedef union {
uint32_t ALL; // Truy cập toàn bộ thanh ghi 32-bit
struct {
uint32_t EN : 1; // Bit 0
uint32_t MODE: 2; // Bit 1–2
uint32_t : 5; // Padding
uint32_t DATA: 24; // Bit 8–31
} BITS;
} REG_CTRL_t;
// Dùng:
REG_CTRL_t reg;
reg.ALL = 0xAABBCCDD;
printf("%d", reg.BITS.MODE); // Lấy MODE từ bit-field
🧾 5. Tổng kết so sánh
| Thuộc tính | struct | union |
| Các thành viên độc lập | ✅ | ❌ |
| Chia sẻ vùng nhớ | ❌ | ✅ |
| Truy cập đồng thời nhiều trường | ✅ | ⚠️ Không an toàn |
| Tối ưu bộ nhớ | ❌ | ✅ |
| Dễ hiểu, trực quan | ✅ | ⚠️ Dễ gây lỗi nếu dùng sai |
| Dùng để map dữ liệu kiểu khác nhau | ❌ | ✅ |