1. 程式人生 > >可變大小結構體如何定義詳解

可變大小結構體如何定義詳解

pan 動態分配 很多 假設 spa 浪費 使用數組 緩沖 發送

一、背景

  工作中,在通信協議中常常看到TLV格式數據,不同的type id對應的字符串長度大小不一樣。那麽該怎麽去定義一個結構體去管理這些數據呢?怎麽去定義一種可變大小的結構體?本文將講解如何定義可變大小結構體。

二、定義可變大小結構體

1、方法一:使用指針

1 typedef struct _S_HB_TIME_REPORT_INFO
2 {
3     uint16_t msg_id;
4     uint16_t msg_buf_len;
5     char *p_msg_buf;
6 }__attribute__((packed)) S_HB_TIME_REPORT_INFO;

  如上定義的結構體,成員變量p_msg_buf為一個指針,指向一個不確定長度的字符串,長度由msg_buf_len決定。在使用時可以動態給p_msg_buf分配msg_buf_len的內存,也可以p_msg_buf指向一個已知地址的字符串。

  缺點:1)動態分配內存使用malloc,在使用之後容易忘記free,此時會產生內存泄漏。 2)如果你使用S_HB_TIME_REPORT_INFO結構體的次數比較多,那麽就要malloc很多次,此時很容易產生內存碎片。我的建議是,能不使用malloc就盡量不要用malloc。我的通常做法是讓p_msg_buf指向一個已知地址的字符串。 3)不管是malloc分配內存還是靜態指向一個已知地址的字符串,結構體裏面的成員變量char *p_msg_buf是與結構體分離的,不利於操作。

2、方法二:使用柔性數組

  2.1 什麽是柔性數組?

  柔性數組既數組大小待定的數組, C語言中結構體的最後一個元素可以是大小未知的數組,也就是所謂的0長度,所以我們可以用結構體來創建柔性數組。

2.2 柔性數組有什麽用途 ?

  它的主要用途是為了滿足需要變長度的結構體,為了解決使用數組時內存的冗余和數組的越界問題。

  3.3 用法

  在一個結構體的最後 ,申明一個長度為空的數組,就可以使得這個結構體是可變長的。對於編譯器來說,此時長度為0的數組並不占用空間,因為數組名本身不占空間,它只是一個偏移量, 數組名這個符號本身代 表了一個不可修改的地址常量 (註意:數組名永遠都不會是指針! ),但對於這個數組的大小,我們

可以進行動態分配,對於編譯器而言,數組名僅僅是一個符號,它不會占用任何空間,它在結構體中,只是代表了一個偏移量,代表一個不可修改的地址常量!對於柔性數組的這個特點,很容易構造出變成結構體,如緩沖區,數據包等等。

1 typedef struct _S_HB_TIME_REPORT_INFO
2 {
3     uint16_t msg_id;
4     uint16_t msg_buf_len;
5     char msg_buf[0];
6 }__attribute__((packed)) S_HB_TIME_REPORT_INFO;

  我們可以用sizeof(S_HB_TIME_REPORT_INFO) 求得數組大小為4,說明柔性數組是不占用內存的。這樣的變長數組常用於網絡通信中構造不定長數據包,不會浪費空間浪費網絡流量,比如我要發送1024字節的數據,如果用定長包,假設定長包的長度為2048,就會浪費1024個字節的空間,也會造成不必要的流量浪費。

  所以建議使用柔性數組去定義可變大小結構體。

可變大小結構體如何定義詳解