今天浏覽酷殼上一篇文章http://coolshell.cn/articles/11377.html時,發現了有關“零長度的數組”的一些知識,其實之前在論壇中也見過這種用法,但是當時對此不太理解,時間一長就慢慢淡忘了該知識點。於是今天特意查了資料,總算弄清“零長度的數組”即柔性數組這一知識點,現在記錄如下。
零長度的數組一般見於結構體中,而直接聲明零長度數組,例如,
char str[0];是無法編譯通過的。而網上說零長度的數組一般是放在結構體的最後一個成員的位置處,但是我試了下,放在中間也是可以的。
先說說放在最後位置處的情況:
結構體聲明如下:
struct str { int len; int b; char s[0]; };注意這裡可能也無法編譯通過,沒關系,改為char s[];這樣就可以了。這裡的char s[0]指的是一個變長數組,也相當於指針吧,不過跟指針卻有本質的區別,如果聲明成指針,那麼指針指向的內存空間可能跟成員b的空間不連續,而聲明成char s[0]則是連續的。
這裡你可能對結構體struct str的大小不太明確,到底是是多少呢?經過測試發現是8,即sizeof(int) + sizeof(int),也就是說s指向的空間不屬於結構體str,這塊空間緊跟著結構體str所代表的空間。
上文指出char s[0]指向的空間緊跟著結構體所代表的空間,因此對於一個struct str *型的指針變量申請內存有如下方法:
s = (struct str *)malloc(sizeof(struct str) + 10);表示給s申請了10個字節的空間。
#include#include #include struct str { int len; int b; char s[0]; }; int main(int argc, char *argv[]) { struct str *s = NULL; printf("sizeof(struct str) = %d\n", sizeof(struct str)); s = (str *)malloc(sizeof(struct str) + 10); s->len = 100; s->b = 50; strcpy(&s->s[0], "abc"); puts(s->s); printf("sizeof(struct str) = %d\n", sizeof(struct str)); printf("addr of len = %p, value of len = %d\n", &s->len, s->len); printf("addr of b = %p, value of b = %d\n", &s->b, s->b); printf("addr of s = %p, value of s = %s\n", &s->s, s->s); return 0; }
執行結果為:
sizeof(struct str) = 8 abc sizeof(struct str) = 8 addr of len = 0x9831008, value of len = 100 addr of b = 0x983100c, value of b = 50 addr of s = 0x9831010, value of s = abc
再看看成員char s[0]放在結構體中間位置處:
#include#include #include struct str { int len; char s[0]; int b; }; int main(int argc, char *argv[]) { struct str *s = NULL; printf("sizeof(struct str) = %d\n", sizeof(struct str)); s = (str *)malloc(sizeof(struct str) + 10); s->len = 100; s->b = 50; strcpy(&s->s[0], "abc"); puts(s->s); printf("sizeof(struct str) = %d\n", sizeof(struct str)); printf("addr of len = %p, value of len = %d\n", &s->len, s->len); printf("addr of s = %p, value of s = %s\n", &s->s, s->s); printf("addr of b = %p, value of b = %d\n", &s->b, s->b); return 0; }
sizeof(struct str) = 8 abc sizeof(struct str) = 8 addr of len = 0x8da6008, value of len = 100 addr of s = 0x8da600c, value of s = abc addr of b = 0x8da600c, value of b = 6513249