首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

C語言柔性數組(結構體尾部零長度數組)實現變長結構體

     編輯:關於C

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最佳
指針 + 獨立 malloc2 次分離 (可能不連續)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))) 強制結構體對齊。
  • **C89 兼容**:舊代碼常用 char data[0] (GCC 擴展),C99 標準寫法 char data[],現代編譯器均支援。
  • **調試**:sizeof(pkt->data) 為 0,調試器可能不正確顯示數組內容,需手動按長度查看內存。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved