关于在结构体末尾定义空数组的用法

关于在结构体末尾定义空数组的用法,以前看到过,一直没搞懂,在无意中瞄到了答案,实在是三生有幸,阿米多佛啊


所以就贴出来大家一起分享:


struct ast_exten {
 char *exten;   /* Extension name */
 int matchcid;   /* Match caller id ? */
 char *cidmatch;   /* Caller id to match for this extension */
 int priority;   /* Priority */
 char *label;   /* Label */
 struct ast_context *parent; /* The context this extension belongs to  */
 char *app;    /* Application to execute */
 void *data;   /* Data to use (arguments) */
 void (*datad)(void *);  /* Data destructor */
 struct ast_exten *peer;  /* Next higher priority with our extension */
 const char *registrar;  /* Registrar */
 struct ast_exten *next;  /* Extension with a greater ID */
 char stuff[0];
};


又如:
struct ast_include {
 char *name;  
 char *rname;  /* Context to include */
 const char *registrar;   /* Registrar */
 int hastime;    /* If time construct exists */
 struct ast_timing timing;               /* time construct */
 struct ast_include *next;  /* Link them together */
 char stuff[0];
};


struct ast_ignorepat {
 const char *registrar;
 struct ast_ignorepat *next;
 char pattern[0];
};


这是个广泛使用的常见技巧,常用来构成缓冲区。比起指针,用空数组有这样的优势:
1.不需要初始化,数组名直接就是所在的偏移
2.不占任何空间,指针需要占用int长度空间,空数组不占任何空间。


“这个数组不占用任何内存”,意味着这样的结构节省空间;“该数组的内存地址就和他后面的元素的地址相同”,意味着无需初始化,数组名就是后面元素的地址,直接就能当做指针使用。


这样的写法最适合制作动态buffer。因为可以这样分配空间:
malloc(sizeof(struct XXX)+ buff_len);
看出来好处没有?直接就把buffer的结构体和缓冲区一块分配了。用起来也非常方便,因为现在kongsuzu其实变成了buff_len长度的数组了。
这样的好处是:
一次分配解决问题,省了不少麻烦。大家知道为了防止内存泄漏,如果是分两次分配(结构体和缓冲区),那么要是第二次malloc失败了,必须回滚释放第一个分配的结构体。这样带来了编码麻烦。其次,分配了第二个缓冲区以后,如果结构里面用的是指针,还要为这个指针赋值。同样,在free这个buffer的时候,用指针也要两次free。如果用空数组,所有问题一次解决。
其次,大家知道小内存的管理是非常困难的,如果用指针,这个buffer的struct部分就是小内存了,在系统内存在多了势必严重影响内存管理的性能。要是用空数组把struct和实际数据缓冲区一次分配大块问题,就没有这个问题。


如此看来,用空数组既简化编码,又解决了小内存碎片问题提高了性能,何乐不为?应该广泛采用。


如果你做过操作系统的开发或者嵌入式开发,这种技巧应该是见得滥了呵呵。
---------------------------------------------------------------


这个就是newbiestar() 所说的extension flexible array member,是C99允许的。标准原文如下(第117页):


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. With two
exceptions, the flexible array member is ignored. First, the size of the structure shall be
equal to the offset of the last element of an otherwise identical structure that replaces the
flexible array member with an array of unspecified length.106) Second, when a . (or ->)
operator has a left operand that is (a pointer to) a structure with a flexible array member
and the right operand names that member, it behaves as if that member were replaced
with the longest array (with the same element type) that would not make the structure
larger than the object being accessed; the offset of the array shall remain that of the
flexible array member, even if this would differ from that of the replacement array. If this
array would have no elements, it behaves as if it had one element but the behavior is
undefined if any attempt is made to access that element or to generate a pointer one past

it.


http://hellosq.blog.hexun.com/5248305_d.html


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值