C99中結構中的最後一個元素是未知大小的數組稱為靈活數據結構成員,但是結構中的靈活數組成員前面必須至少有一個其它成員。靈活數組成員也許結構中包含一個可變大小的數組。這種結構的sizeof返回大小不包含靈活數組的內存。包含靈活數組成員的結構使用malloc進行內存動態分配,並且分配的內存應該大於結構的大小,以適應靈活數組的預期大小。 — 摘自《C語言大全》 一個使用靈活數組的示例如下: #include <stdio.h> // 定義一個靈活數組 typedef struct StType { int count; int item[0]; } StType; int main() { printf("sizeof(StType) = %d\n", (int)sizeof(StType)); int val[4] = {3, 1, 2, 3}; StType *st = (StType*)val; for (int i = 0; i < st->count; i++) printf("%d value =%d\n", i, st->item[i]); return 0; } 編譯後運行結果如下: sizeof(StType) = 4 0 value = 1 1 value = 2 2 value = 3 從上面的結果可以看出item[0]並沒有占用空間,這樣我們可以使用malloc或者new來進行變長操作,如下所示。 StType*st = (StType*)new char[sizeof(StType) + 100 * sizeof(int)]; st.count= 100; delete[]st; 上面的代碼生產一個100個item的StType對象,可以使用delete[]st;釋放分配的內存。 這種靈活數組成員(Fleiblearray member)在C89中是不支持的,C99作為一種特例加入到標准中,但是C99所支持的是不完整類型,而不是0數組,使用int item[0];定義是非法的,需要使用int item[]替代它,有些編譯器可以使用是因為編譯器把int item[0]作為非標准來支持。 注:在VC中編譯會提示告警信息,如下: warning C4200: nonstandard extension used :zero-sized array in struct/union Cannot generate copy-ctor orcopy-assignment operator when UDT contains a zero-sized array 注意區分 C99新增的“可變長數組”: C89 標准規定,數組大小必須是在編譯時刻確定的;在C99 中,這個標准項被擴展,可以是運行時刻確定的值。也就是說,可變長數組和 C++ 本身沒有關系,只要是支持 C99 的就可以使用可變長數組,包括支持 C99 的 C 編譯器。 需要注意的是,可變長數組的維數在數組生存期內是不變的,也就是說,可變長數組不是動態的,可變的只是數組的大小。 有時候人們會考慮暫時不存在的兼容性問題,如果把程序移植到只有標准C89編譯器的平台,那下面有幾種可以替代的方法: 1) 方法1 struct header { size_t len; unsigned char data[1]; }; ptr = malloc(sizeof(struct header) + (n -1)); 但這種方法是否有效是有賴於實現的,這破壞了可移植性的規則。 2) 方法2 struct header*my_header = malloc(offsetof(struct header, data) + n * sizeof(my_header->data)); 或者使用宏來簡化代碼: #define FLEXIBLE_SIZE SIZE_MAX // or whatever maximum length for an array #defineSIZEOF_FLEXIBLE(type, member, length) \ (offsetof(type,member) + (length) * sizeof((type*)0)->member[0]) 這種方法過於復雜,而且為了保持C89兼容,看起來沒有什麼特別的好處,你不需要一個完全的C99編譯器就可以使用彈性數組成員。 3) 方法3: 使用指針,不要節約那一次間接引用,如果可移植性那麼重要的話。