零長度陣列

2021-07-15 07:57:10 字數 3138 閱讀 6728

最近在準備分析linux input子系統,發現核心**裡面有很多小技巧。特此記錄下,如有不足之處,敬請指正。

在日常的程式設計中,有時候需要在結構體中存放乙個長度動態的字串,比如說,我們要在結構體中存放乙個名字,但是這個名字的長度是未知的。於是,我們就會採用以下兩種方法來解決這個問題。

注:以下的**都是在下面的平台進行驗證測試的:

linux version 2.6.32-38-generic (buildd@allspice) (gcc version 4.4.3 (ubuntu 4.4.3-4ubuntu5) ) #83-ubuntu smp wed jan 4 11:12:07 utc 2012

碰到上面的情況,一般而言我們會這麼做:首先在結構體中定義乙個指標成員,然後為這個指標成員malloc()一定長度的空間,進而往該空間寫入字串。

#include 

#include

#include

struct node;

char test_name = "testname";

int main(void)

上述**的執行結果為:

sizeof(struct node) = 16

num addr:0x10ba010

data addr:0x10ba014

name addr:0x10ba030

name = testname

name[0] = t

name[7] = e

從中,我們可以看出:

1、如果想要例項化test_node,第一次要為test_node申請大小為sizeof(struct node)的空間,第二次再為其成員name申請lenght大小的空間。

首先我們要呼叫兩次malloc(),呼叫兩次,意味著最後也要跟著free()兩次;其次,如果第二次為name成員申請空間失敗的話,需要返回回去將test_nodefree掉。這樣工作量就上來了,而且容易導致malloc()free()沒對應進而出現記憶體錯誤。

2、我們看到,sizeof(struct node)的大小為16,即4+4+8的大小。這個可以和下面的**進行對比。

3、通過列印test_node三個成員的位址分別為:

num addr:0x10ba010

data addr:0x10ba014

name addr:0x10ba030

很明顯,成員name的位址與成員numdata的位址並不是連續的。小記憶體的管理是非常困難的,如果用指標,這個name的部分就是小記憶體了,在系統內存在多了勢必嚴重影響記憶體管理的效能。要是用空陣列把結構體和實際資料緩衝區一次分配大塊問題,就沒有這個問題。

為了規避上述**的問題,我們採用下面的方法來解決:

#include 

#include

#include

struct node;

char test_name = "testname";

int main(void)

執行結果為:

sizeof(struct node) = 8

num addr:0x1574010

data addr:0x1574014

name addr:0x1574018

test_node+1 addr:0x1574018

name = testname

name[0] = t

name[7] = e

通過比較,我們不難看出:

1、此時,例項化test_node只呼叫一次malloc(),意味著最後也只要free()一次。為其申請了乙個長度為sizeof(struct node)+lenght的空間,所申請到的空間是連續的,沒有小記憶體的情況出現。減小了對記憶體管理效能的影響。

2、同樣的,sizeof(struct node)為8,即4+4,因此我們可以知道這裡的成員name並沒有占用空間,即使占用乙個指標大小的空間都沒有,因此這種方式可以節省空間。

3、此時test_node三個成員的位址分別為:

num addr:0x1574010

data addr:0x1574014

name addr:0x1574018

可以明顯的看到,這個位址是連續的。因為我們只malloc()一次。

4、並且,我們還知道test_node+1的位址和test_node->name的位址是一樣的,說明兩者指向同一塊記憶體區域,這更進一步的驗證了成員name並沒有占用空間。

c99使用不完整型別實現柔性陣列成員,在c99 中,結構中的最後乙個元素允許是未知大小的陣列,這就叫做柔性陣列(flexible array)成員(也叫伸縮性陣列成員),但結構中的柔性陣列成員前面必須至少乙個其他成員。柔性陣列成員允許結構中包含乙個大小可變的陣列。柔性陣列成員只作為乙個符號位址存在,而且必須是結構體的最後乙個成員,sizeof 返回的這種結構大小不包括柔性陣列的記憶體。柔性陣列成員不僅可以用於字元陣列,還可以是元素為其它型別的陣列。包含柔性陣列成員的結構用malloc ()函式進行記憶體的動態分配,並且分配的記憶體應該大於結構的大小,以適應柔性陣列的預期大小。

第八章 柔性陣列成員

結構體中最後乙個成員為[0]或[1]長度陣列(柔性陣列成員)的用法

零長度陣列

零長度陣列 神奇的int reserve 0 include include struct device 構題 device 之後 這種宣告方法可以巧妙的實現c語 言裡的陣列擴充套件 int main a.out p dev reserve 0 100 p dev reserve 24 0 size...

零長度陣列

適用於c語言變長陣列 在實際的程式設計中,我們經常需要使用變長陣列,但是c語言並不支援變長的陣列。此時,我們可以使用結構體的方法實現c語言變長陣列。struct mydata 在結構中,data是乙個陣列名 但該陣列沒有元素 該陣列的真實位址緊隨結構體mydata之後,而這個位址就是結構體後面資料的...

整理 零長度陣列

零長度陣列 gnu c 允許使用零長度陣列,在定義變長物件的頭結構時,這個特性非常有用。例 如 include linux minix fs.h struct minix dir entry 結構的最後乙個元素定義為零長度陣列,它不佔結構的空間。在標準 c 中則需要 定義陣列長度為 1,分配時計算物...