设为首页 加入收藏

TOP

C语言中的柔性数组
2014-11-23 19:52:17 来源: 作者: 【 】 浏览:9
Tags:言中 柔性

今天浏览酷壳上一篇文章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

可以看出s确实是排在成员b的后面!尽管表面上看s是结构体str的成员,但实际上并不是;这样做的好处就是可以一次性将所需的内存空间申请出来(所以内存是连续的,内存碎片也减少了),因为如果是以指针形式声明的,那么就必须做两次内存申请(结构体一次,成员s一次)。

再看看成员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

可以清楚的看出s和b的地址是一样的,对s赋值,结果将b的值给覆盖了,有点像联合体哈!

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇开灯问题(语言入门) 下一篇最小堆 / 优先队列(C语言实现)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: