C99 標準引入**柔性數組成員** (Flexible Array Member),允許結構體最後一個成員為不定長度數組 type name[] (或舊式 type name[0]),實現變長結構體,廣泛用於網絡封包、數據庫記錄、內核數據結構。
struct Packet {
uint16_t len;
uint8_t data[]; // 柔性數組,必須是最後一個成員
};
// 結構體大小 = 固定部分大小 (不含柔性數組)
// sizeof(struct Packet) == sizeof(uint16_t) == 2 (可能含填充對齊)
sizeof **不包含**柔性數組空間。
struct Packet *pkt = malloc(sizeof(struct Packet) + 100); // 分配固定頭 + 100字節數據
pkt->len = 100;
memcpy(pkt->data, payload, 100); // 直接操作 data 成員
// 釋放時只需 free(pkt),單次分配單次釋放,無內存碎片
free(pkt);
| 方案 | 分配次數 | 內存連續性 | 釋放操作 | 緩存局部性 |
|---|---|---|---|---|
| 柔性數組 | 1 次 | 完全連續 | 1 次 free | 最佳 |
| 指針 + 獨立 malloc | 2 次 | 分離 (可能不連續) | 2 次 free | 較差 |
#include
#include
#include
struct MyData {
int nLen;
char data[]; // C99 標準寫法,GCC 也支援 data[0]
};
int main() {
const char *str = "Hello, Flexible Array!";
int len = strlen(str);
struct MyData *obj = malloc(sizeof(struct MyData) + len + 1); // +1 存 \0
obj->nLen = len;
memcpy(obj->data, str, len + 1);
printf("Size of struct: %zu\n", sizeof(struct MyData)); // 輸出 4 或 8 (視對齊)
printf("Data: %s (len=%d)\n", obj->data, obj->nLen);
free(obj);
return 0;
}
Size of struct: 4 Data: Hello, Flexible Array! (len=22)
// 通用鏈表節點,數據緊跟節點頭
struct ListNode {
struct ListNode *next;
uint8_t data[]; // 極簡容器
};
// 分配帶 64 字節數據的節點
struct ListNode *node = malloc(sizeof(struct ListNode) + 64);
node->next = head;
memcpy(node->data, buffer, 64);
head = node;
struct Packet pkt; 非法,柔性數組無大小無法分配棧空間。__attribute__((aligned(8))) 強制結構體對齊。char data[0] (GCC 擴展),C99 標準寫法 char data[],現代編譯器均支援。sizeof(pkt->data) 為 0,調試器可能不正確顯示數組內容,需手動按長度查看內存。