你了解C語言的「柔性數組」嗎?看完你就知道了

2019-11-13     C語言編程開發

C語言

首先我們來看一道面試題
如果你還不能很快就得出答案,那可以通過本次的介紹徹底的了解一下「柔性數組」

參考答案會在文末給出哦


開發C代碼時,經常見到如下類型的結構體定義:

typedef struct list_t{
struct list_t *next;
struct list_t *prev;
char data[0];
}list_t;

最後一行char data[0];的作用是()

A、方便管理內存緩衝區

B、減少內存碎片化

C、標識結構體結束

D、沒有作用

柔性數組(Flexible Array)是C99引入的一個新特性
這個特性允許你在定義結構體的時候創建一個空數組,而這個數組的大小可以在程序運行的過程中根據你的需求進行更改
特別注意的一點是:
這個空數組必須聲明為結構體的最後一個成員,並且還要求這樣的結構體至少包含一個其他類型的成員

上面的簡單介紹可能還是沒能讓你足夠了解什麼是「柔性數組」,以及具體又該如何使用,下面就通過具體的例子進行解釋:

現在我們需要進行學生的一些基本信息的統計,假設我們定義了如下的一個結構體:

typedef struct
{
int stuID;
int name;
char address[30];
}ST_STU_INFO

可以看到在最後存儲「地址(address)「的結構體中,我們申請了一個包含30個位元組的數組,如果我們存儲的時候只存入較短的地址,以上的定義的是沒問題的,但需要存入的地址信息超出了30個位元組,程序很可能就崩掉了,就像下面這樣

C語言

這時候具有主角光環的柔性數組就可以登場啦!

我們在結構體中定義一個柔性數組,這樣可以確保能夠在程序運行過程中「動態」的進行結構體的擴展,是有點動態的感覺了呀!
具體代碼如下:

#include#include#include

//存放學生信息結構體
typedef struct{
int stuID;
int age;
char address[];
}ST_STU_INFO,*pStuInfo;

//為結構體分配內存
pStuInfo ComposeStuInfo( int stuID,int age, const char *paddress)
{
pStuInfo ptmpInfo = malloc(sizeof(*ptmpInfo) + sizeof(char) * strlen(paddress) + 1);
if(ptmpInfo != NULL){
ptmpInfo->stuID = stuID;
ptmpInfo->age = age;
strcpy(ptmpInfo->address, paddress);
}
return ptmpInfo;
}

// 列印學生信息
void printStuInfo(pStuInfo ptmpInfo)
{
printf("stuID : %d age : %d Address: %s\\nSize of Struct:%d\\n\\n",
ptmpInfo->stuID,ptmpInfo->age,ptmpInfo->address,sizeof(*ptmpInfo));
}

//主程序
int main()
{
pStuInfo CodeLab = ComposeStuInfo(100013,20, "Tencent Building, Central District, High-tech Park, Nanshan District, Shenzhen");
if(CodeLab != NULL){
printStuInfo(CodeLab);
free(CodeLab);
}
pStuInfo subCodeLab = ComposeStuInfo(200013,23, "Tencent Building");//Tencent Building裡面的大佬個個都很厲害吧~~~
if(subCodeLab != NULL){
printStuInfo(subCodeLab);
free(subCodeLab);
}
return 0;
}

運行之後得到結果如下:

stuID : 100013 age : 20 Address: Tencent Building, Central District, High-tech Park, Nanshan District, Shenzhen
Size of Struct:8

stuID : 200013 age : 23 Address: Tencent Building
Size of Struct:8

從結果輸出可以看到,我們成功使用了不同長度的地址,當然程序也不會出現文章開頭那樣崩潰的情況

此外,雖然我們對結構體進行了如下的初始化

pStuInfo ptmpInfo = malloc(sizeof(*ptmpInfo) + sizeof(char) * strlen(paddress) + 1);

但是卻在輸出中可以看到結構體的大小並沒有因此而發生變化

Size of Struct:8

ST_STU_INFO結構體的大小是8, 兩個int型變量大小剛好為8,也就是說結構體中的數組並沒有占用內存,這就是從0開始,卻可以拓展的柔性數組

針對柔性數組這一不占用內存的特性,可以構造出內存緩衝區,同時由於是使用多少就申請多少,也起到了減少內存碎片化的作用,所以文章開頭的面試題答案是A和B

而對於選項C而言,恰恰相反的是,柔性數組並不是標識結構體結束,而是作為結構體的一種拓展

同時也可以理解為柔性數組為結構體的一個偏移地址,這使得結構體的大小可以進行動態的變化


最後可能還是會有疑問,這和直接使用指針有啥區別呢?
像下面這樣:

typedef struct{
int stuID;
int age;
char *pAddress;
}ST_STU_INFO;

首先柔性數組不占用內存,而指針則不然,此外柔性數組在使用上是直接訪問,形式上更加直觀,而指針需要經過聲明再進行動態分配內存,在效率上和柔性數組相比也稍微低一些,其實在Linux內核代碼中有較多的柔性數組的使用,感興趣的可以去深入的了解一下。

C語言

小夥伴們在學習的過程中難免會遇到很多的困難,有的是初學不知道如何入手,亦或是想要繼續提升自己,小編為了幫助大家解決學習問題,大家可+企鵝,裙 546-912-356我將會針對性的幫助解答你學習上的問題和發送你學習資料哦,大家一起進步!

好了,就講到這裡吧,感謝耐心閱讀!

文章來源: https://twgreatdaily.com/zh-tw/M5jeY24BMH2_cNUgFNcY.html