天天看點

番外篇17:柔性數組了解及當做不定長協定講解(有代碼)

文章目錄

    • 1.需求
    • 2.使用條件
    • 3.怎麼使用?(代碼)
    • 4.可能遇到的問題
    • 5.不定長協定當協定

1.需求

  • 在日常的程式設計中,有時候需要在結構體中存放一個長度動态的字元串,一般的做法,是在結構體中定義一個指針成員,這個指針成員指向該字元串所在的動态記憶體空間
  • 但是:針對以上問題 可以有一個更優的解決方案即,在結構體的尾部放置一個0長度的數組是一個絕妙的解決方案,我們既能直接引用該字元串,又不占用結構體的空間。不過,C/C++标準規定不能定義長度為0的數組,是以,有些編譯器就把0長度的數組成員作為自己的非标準擴充。
typedef struct
 {
    WORD usMsgID;
    WORD usMsgLen;
    char pData[0];//柔性數組
 }FLEXIBLE_DEF_STRU;
           
  • 有些編譯器會報錯無法編譯可以改成
typedef struct
 {
    WORD usMsgID;
    WORD usMsgLen;
    //大小可變,最佳設計是該改為char Data[1],真正標頭大小為sizeof(FLEXIBLE_DEF_STRU)- sizeof(char)
    char pData[];
 }FLEXIBLE_DEF_STRU;
           

2.使用條件

①結構體中的柔性數組成員前面必須至少一個其他成員。

②柔性數組必須是結構體的最後一個成員。

③柔性數組成員隻作為一個符号位址存在,sizeof 傳回的這種結構大小不包括柔性數組的記憶體。

④包含柔性數組成員的結構用malloc ()函數進行記憶體的動态配置設定,并且配置設定的記憶體應該大于結構體的大小,以适應柔性數組的預期大小。

⑤柔性數組成員不僅可以用于字元數組,還可以是元素為其它類型的數組。

⑥記憶體已經配置設定了,數組的長度是可以通過計算出來的

3.怎麼使用?(代碼)

char szDataInfo[] = "hello world";  
//malloc記憶體大小為結構體大小+資料大小,包含‘\0’
FLEXIBLE_DEF_STRU *pTest = (FLEXIBLE_DEF_STRU *)malloc(sizeof(FLEXIBLE_DEF_STRU)+sizeof(szDataInfo));

char szInfo[] = "hello world";  
FLEXIBLE_DEF_STRU *pTest = (FLEXIBLE_DEF_STRU *)malloc(sizeof(FLEXIBLE_DEF_STRU)+sizeof(szInfo));
pTest->usMsgID      = 0x1234;
pTest->usMsgLen     = sizeof(szInfo);

//若拷貝的内容是字元串,注意'\0'也需要被拷貝走,
//是以使用sizeof(),不能是strlen()
memcpy_s(pTest->pData,pTest->usMsgLen,szInfo, sizeof(szInfo));
printf("%s\n",pTest->pData);

//隻需要釋放一次記憶體
SAFE_FREE(pTest);


           

4.可能遇到的問題

  • 對于包含有柔性數組的結構體,我們對記憶體的申請和釋放隻需要一次。因為我們的資料區buffer緊随在結構體之後,資料和結構體在同一個記憶體塊中,是以我們隻需要釋放一次,示意圖如下:
    番外篇17:柔性數組了解及當做不定長協定講解(有代碼)
  • 我們應當盡量使用标準形式,在非C99的場合,可以使用指針方法。需要說明的是:C89不支援這種東西,C99把它作為一種特例加入了标準。但是,C99所支援的是incomplete type,而不是zero array,形同int a[0];這種形式是非法的,C99 支援的形式是形同int a[];隻不過有些編譯器把int a[0];作為非标準擴充來支援,而且在C99 釋出之前已經有了這種非标準擴充了,C99 釋出之後,有些編譯器把兩者合而為一了。

5.不定長協定當協定

繼續閱讀