【什麼是柔性數組(Fiexibel Array)】html
柔性數組在C99中的定義是:數組
6.7.2.1 Structure and union specifiersapp
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.函數
因此能夠給出一箇中文定義:測試
在至少兩個成員的結構體中,最後一個成員其類型如果不完整類型的數組類型,則該成員稱爲柔性數組。flex
典型例子:this
struct s { int n; char str[]; };
注意,str後面的中括號只能爲空,數組類型不侷限於char。spa
然而GCC編譯器在C99發佈以前就支持str[0]做爲「柔性數組」,並且str[0]能夠放在任何位置。這屬於GCC對C語言的語法擴展。設計
這個語法擴展由於實用而且受歡迎,因此C99將其做爲一個特殊狀況並獲得了支持。下面將具體說明。code
【柔性數組的由來和做用】
有一些應用場景(如設計數據包)須要一個結構體裏面包含因時而異的字符串,沒有「柔性數組」概念以前,使用的方法是:
#include <stdio.h> #include <string.h> #include <stdlib.h> int main(void) { struct s { int n; char *str; }; char string[] = "ZhangHaiba"; struct char *ptos = malloc(sizeof (struct s) + strlen(string)+1); strcpy(ptos+1, string); //get the beginning address of str char *p = (char *)(ptos+1); printf("%s\n", p); return 0; }
GCC超越當時的標準對C語法進行擴展,支持「柔性數組」,就可使用下面的方法(移植性很差):
#include <stdio.h> #include <string.h> #include <stdlib.h> int main(void) { struct s { int n; char str[0]; }; char string[] = "ZhangHaiba"; struct s *ptos = malloc(sizeof (struct s) + strlen(string)+1); strcpy(ptos->str, string); //get the beginning address of str char *p = ptos->str; printf("%s\n", p); return 0; }
下面是GCC關於「柔性數組」的官方介紹和對比:http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
因爲上述方法符合C語言的精神(代碼簡單精煉),所以在C99中獲得了支持。因此符合C99標準並且優雅的方法應該是:
#include <stdio.h> #include <string.h> #include <stdlib.h> int main(void) { struct s { int n; char str[]; }; char string[] = "ZhangHaiba"; struct s *ptos = malloc(sizeof (struct s) + sizeof (string)); strcpy(ptos->str, string); //get the beginning address of str char *p = ptos->str; printf("%s\n", p); return 0; }
【C99柔性數組的特色】
柔性數組做爲不完整類型,即便用struct s test定義了變量test以後,sizeof (test.str)確定是不行的。哪怕給str分配了空間也不行。
由於標準規定sizeof的操做數不能夠是不完整類型(還有函數類型及位字段)。
因此sizeof (struct s)或sizeof (test),不算上柔性數組str佔的空間,也是情理之中了。(若是在GCC中,單獨測試array[0],則顯示其佔空間爲0字節)
簡而言之,柔性數組只是把符號(名字)放在結構體內(壓根兒就沒定義),方便使用.或->語法來操做柔性數組,其所佔內存空間(定義時分配)並不算在結構體變量中。
#include <stdio.h> #include <string.h> #include <stdlib.h> int main(void) { struct s { int n; char str[]; }; char string[] = "ZhangHaiba"; struct s *ptos = malloc(sizeof (struct s) + sizeof (string)); strcpy(ptos->str, string); //get the beginning address of str char *p = ptos->str; printf("%s\n", p); struct s test; //test is static allocation,str didn't alloc memory printf("%ld %ld\n", sizeof test, sizeof *ptos); // *ptos is dynamic allocation, str has been alloc memory //printf("%ld\n", sizeof (test.str)); //error: invalid application of ‘sizeof’ to incomplete type ‘char[]’ //printf("%ld\n", sizeof (ptos->str)); //error: invalid application of ‘sizeof’ to incomplete type ‘char[]’ return 0; }
@Author: 張海拔
@Update: 2014-2-2
@Link: http://www.cnblogs.com/zhanghaiba/p/3537561.html