結構中最後一個元素允許是未知大小的數組,這個數組就是柔性數組。但結構中的柔性數組前面必須至少一個其他成員,柔性數組成員允許結構中包含一個大小可變的數組,sizeof傳回的這種結構大小不包括柔性數組的記憶體。包含柔數組成員的結構用malloc函數進行記憶體的動态配置設定,且配置設定的記憶體應該大于結構的大小以适應柔性數組的預期大小。柔性數組到底如何使用?
c和c++對于不完整類型的定義是一樣的,不完整類型是這樣一種類型,它缺乏足夠的資訊例如長度去描述一個完整的對象。
不完整類型舉例:
前向聲明就是一種常用的不完整類型
不完整資料類型必須通過某種方式補充完整,才能使它們進行執行個體化。否則隻能用于定義指針或引用,因為此時執行個體化的是指針或引用本身,不是base和test對象
一個未知長度的數組也屬于不完整類型:
extern 關鍵字不能去掉,因為數組的長度未知,不能作為定義出現。不完整類型的數組需要補充完整才能使用。不完整類型的數組可以通過幾種方式補充完整,大括号形式的初始化就是其中的一種方式:
首先,我們需要知道——所謂變量,其實是記憶體位址的一個抽像名字罷了。在靜态編譯的程式中,所有的變量名都會在編譯時被轉成記憶體位址。機器是不知道我們取的名字的,隻知道位址。
是以有了——棧記憶體區,堆記憶體區,靜态記憶體區,常量記憶體區,我們代碼中的所有變量都會被編譯器預先放到這些記憶體區中。
有了上面這個基礎,我們來看一下結構體中的成員的位址是什麼?我們先簡單化一下代碼:
上面代碼中,test結構中i和p指針,在c的編譯器中儲存的是相對位址——也就是說,他們的位址是相對于struct test的執行個體的。如果我們有這樣的代碼:
下面做個實驗:
運作結果:

我們可以看到,t.i的位址和t的位址是一樣的,t.p的址址相對于t的位址多了個8。說白了,t.i 其實就是(&t + 0×0), t.p 的其實就是 (&t + 0×8)。0×0和0×8這個偏移位址就是成員i和p在編譯時就被編譯器給hard code了的位址。于是,你就知道,不管結構體的執行個體是什麼——通路其成員其實就是加成員的偏移量。
下面再來做個實驗:
柔性數組成員(flexible array
member)也叫伸縮性數組成員,這種代碼結構産生于對動态結構體的需求。在日常的程式設計中,有時候需要在結構體中存放一個長度動态的字元串,一般的做
法,是在結構體中定義一個指針成員,這個指針成員指向該字元串所在的動态記憶體空間,例如:
p指向字元串,這種方法造成字元串與結構體是分離的,不利于操作。把字元串和結構體連在一起的話,效果會更好,可以修改如下:
這樣一來,(char*)(ptestt + 1)就是字元串“hello
world”的位址。這時候p成了多餘的東西,可以去掉。但是,又産生了另外一個問題:老是使用(char*)(ptestt +
1)不友善。如果能夠找出一種方法,既能直接引用該字元串,又不占用結構體的空間,就完美了,符合這種條件的代碼結構應該是一個非對象的符号位址,在結構
體的尾部放置一個0長度的數組是一個絕妙的解決方案。不過,c/c++标準規定不能定義長度為0的數組,是以,有些編譯器就把0長度的數組成員作為自己的
非标準擴充,例如:
c就叫柔性數組成員,如果把ptest指向的動态配置設定記憶體看作一個整體,c就是一個長度可以動态變化的結構體成員,柔性一詞來源于此。c的長度為
0,是以它不占用test的空間,同時ptest->c就是“hello world”的首位址,不需要再使用(char*)(ptestt +
1)這麼醜陋的文法了。
鑒于這種代碼結構所産生的重要作用,c99甚至把它收入了标準中:
as a special case, the last element of a structure with more than one
named member may have an incomplete array type; this is called a
flexible array member.
c99使用不完整類型實作柔性數組成員,标準形式是這樣的:
c同樣不占用test的空間,隻作為一個符号位址存在,而且必須是結構體的最後一個成員。柔性數組成員不僅可以用于字元數組,還可以是元素為其它類型的數組,例如:
首先,我們要知道,0長度的數組在iso c和c++的規格說明書中是不允許的。這也就是為什麼在vc++2012下編譯你會得到一個警告:“arning c4200: 使用了非标準擴充 : 結構/聯合中的零大小數組”。
上面這段代碼的意思是:我想配置設定一個不定長的數組,于是我有一個結構體,其中有兩個成員,一個是length,代表數組的長度,一個是contents,代碼數組的内容。後面代碼裡的 this_length(長度是10)代表是想配置設定的資料的長度。