今天浏览酷壳上一篇文章http://coolshell.cn/articles/11377.html时,发现了有关“零长度的数组”的一些知识,其实之前在论坛中也见过这种用法,但是当时对此不太理解,时间一长就慢慢淡忘了该知识点。于是今天特意查了资料,总算弄清“零长度的数组”即柔性数组这一知识点,现在记录如下。
零长度的数组一般见于结构体中,而直接声明零长度数组,例如,
char str[0];
是无法编译通过的。而网上说零长度的数组一般是放在结构体的最后一个成员的位置处,但是我试了下,放在中间也是可以的。
先说说放在最后位置处的情况:
结构体声明如下:
struct str
{
int len;
int b;
char s[0];
};
注意这里可能也无法编译通过(C99编译失败,C11编译成功),没关系,改为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