結構體中最后一個成員為[0]或[1]長度數組(柔性數組成員)的用法
結構體中最后一個成員為[0]長度數組的用法:這是個廣泛使用的常見技巧,常用來構成緩沖區。比起指針,用空數組有這樣的優勢:(1)、不需要初始化,數組名直接就是所在的偏移;(2)、不占任何空間,指針需要占用int長度空間,空數組不占任何空間。“這個數組不占用任何內存”,意味著這樣的結構節省空間;“該數組的內存地址就和它后面的元素地址相同”,意味著無需初始化,數組名就是后面元素的地址,直接就能當指針使用。
這樣的寫法最適合制作動態buffer,因為可以這樣分配空間malloc(sizeof(structXXX) + buff_len); 直接就把buffer的結構體和緩沖區一塊分配了。用起來也非常方便,因為現在空數組其實變成了buff_len長度的數組了。這樣的好處是:(1)、一次分配解決問題,省了不少麻煩。為了防止內存泄露,如果是分兩次分配(結構體和緩沖區),那么要是第二次malloc失敗了,必須回滾釋放第一個分配的結構體。這樣帶來了編碼麻煩。其次,分配了第二個緩沖區以后,如果結構里面用的是指針,還要為這個指針賦值。同樣,在free這個buffer的時候,用指針也要兩次free。如果用空數組,所有問題一次解決。(2)、小內存的管理是非常困難的,如果用指針,這個buffer的struct部分就是小內存了,在系統內存在多了勢必嚴重影響內存管理的性能。要是用空數組把struct和實際數據緩沖區一次分配大塊問題,就沒有這個問題。如此看來,用空數組既簡化編碼,又解決了小內存碎片問題提高了性能。
結構體最后使用0或1長度數組的原因:主要是為了方便的管理內存緩沖區(其實就是分配一段連續的內存,減少內存的碎片化),如果直接使用指針而不使用數組,那么,在分配內存緩沖區時,就必須分配結構體一次,然后再分配結構體內的指針一次,(而此時分配的內存已經與結構體的內存不連續了,所有要分別管理即申請和釋放)而如果使用數組,那么只需要一次就可以全部分配出來,反過來,釋放時也是一樣,使用數組,一次釋放。使用指針,得先釋放結構體內的指針,再釋放結構體,還不能顛倒順序。
結構體中最后一個成員為[1]長度數組的用法:與長度為[0]數組的用法相同,改寫為[1]是出于可移植性的考慮。有些編譯器不支持[0]數組,可將其改成[]或[1].
不完整類型(incomplete type):它缺乏足夠的信息例如長度去描述一個完整的對象。(1)、前向聲明就是一種常用的不完整類型, class base; struct test; base和test只給出了聲明,沒有給出定義。不完整類型必須通過某種方式補充完整,才能使用它們進行實例化,否則只能用于定義指針或引用,否則只能用于指針或引用,因為此時實例化的是指針或引用本身,不是base或test對象。(2)、一個未知長度的數組也屬于不完整類型:extern int a[]; extern不能去掉,因為數組的長度未知,不能作為定義出現。不完整類型的數組可以通過幾種方式補充完整才能使用,大括號形式的初始化就是其中一種方式:int a[] = {10, 20};
柔性數組成員(flexible array member):也叫收縮性數組成員,這種代碼結構產生于對動態結構體的需求。C99使用不完整類型實現柔性數組成員,在C99中,結構中的最后一個元素允許是未知大小的數組,這就叫柔性數組成員。但結構中的柔性數組成員前面必須至少一個其它成員。柔性數組成員允許結構中包含一個大小可變的數組。柔性數組成員只作為一個符號地址存在,而且必須是結構體的最后一個成員,sizefo返回的這種結構大小不包括柔性數組的內存。柔性數組成員不僅可以用于字符數組,還可以是元素為其它類型的數組。包含柔性數組成員的結構用malloc()函數進行內存的動態分配,并且分配的內存應該大于結構的大小,以適應柔性數組的預期大小。
C/C++標準規定不能定義長度為0的數組,因此,有些編譯器就把0長度的數組成員作為自己的非標準擴展。
示例代碼:
[cpp] view plaincopy

- #include <iostream>
- using namespace std;
- typedef struct _FlexibleArray
- {
- char ch;
- int arr[0];//int arr[];//int arr[1];
- }FlexibleArray;
- int main()
- {
- cout<<sizeof(FlexibleArray)<<endl;
- const int LENGTH = 10;
- FlexibleArray* flexibleArray = (FlexibleArray*)new char[sizeof(FlexibleArray) + LENGTH * sizeof(int)];
- for (int i = 0; i < LENGTH; i ++) {
- flexibleArray->arr[i] = i * i;
- }
- for (int i = 0; i < LENGTH; i ++) {
- cout<<flexibleArray->arr[i]<<endl;
- }
- delete [] flexibleArray;
- return 0;
- }
參考文獻:
1、 http://blog.chinaunix.net/uid-26750459-id-3191136.html
2、 http://blog.csdn.net/ce123_zhouwei/article/details/8973073
3、 http://blog.csdn.net/code_crash/article/details/4854939
RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成