Đặc điểm của Flexible Array Members
Flexible Array Members (FAM) là tính năng được thêm vào C99 cho phép khai báo mảng không xác định kích thước trong cấu trúc dữ liệu. Đặc điểm nổi bật:
- Kích thước xác định tại thời điểm chạy
- Không chiếm không gian cố định trong cấu trúc
- Phải là thành viên cuối cùng của struct
Ví dụ minh họa
Xét cấu trúc Document sau:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char docTitle[100];
char docAuthor[50];
char content[]; // Flexible array member
} Document;
int main() {
const char* title = "Hướng dẫn C nâng cao";
const char* author = "Nguyen Van A";
const char* body = "Chương 1: Quản lý bộ nhớ...";
size_t size = sizeof(Document) + strlen(body) + 1;
Document* doc = malloc(size);
if (doc) {
strcpy(doc->docTitle, title);
strcpy(doc->docAuthor, author);
strcpy(doc->content, body);
printf("Tài liệu: %s\n", doc->docTitle);
printf("Nội dung: %s\n", doc->content);
free(doc);
}
return 0;
}
Quy tắc sử dụng
- Vị trí bắt buộc: FAM phải là thành viên cuối cùng trong struct
- Cấp phát bộ nhớ: Tính toán tổng kích thước = sizeof(struct) + kích thước mảng
- Giải phóng: Chỉ cần free() toàn bộ cấu trúc
So sánh với mảng thông thường
| Flexible Array | Mảng cố định |
|---|---|
| Kích thước thay đổi | Kích thước cố định |
| Tối ưu bộ nhớ | Có thể gây lãng phí |
| Cấp phát động | Cấp phát tĩnh |
Ứng dụng nâng cao
1. Bộ đệm động
typedef struct {
int bufferSize;
char bufferData[];
} DynamicBuffer;
DynamicBuffer* createBuffer(int size) {
DynamicBuffer* buf = malloc(sizeof(DynamicBuffer) + size);
if (buf) buf->bufferSize = size;
return buf;
}
2. Cấu trúc lồng nhau
typedef struct {
char name[40];
char bio[];
} UserProfile;
typedef struct {
int userCount;
UserProfile users[];
} UserDatabase;
// Cấp phát cơ sở dữ liệu người dùng
size_t total = sizeof(UserDatabase) + 2 * sizeof(UserProfile) + 200;
UserDatabase* db = malloc(total);
Nguyên tắc an toàn
- Kiểm tra kết quả malloc()
- Không thêm thành viên sau FAM
- Tránh sao chép cấu trúc bằng assignment
- Không dùng FAM trong union