柔性数组 元素个数为0的数组 变长数组
来源:互联网 发布:可口可乐表白软件 编辑:程序博客网 时间:2024/04/30 05:52
在Linux源代码中,有很多的结构体最后都定义了一个元素个数为0个的数组,如/usr/include/linux/if_pppox.h中有这样一个结构体:
struct pppoe_tag {
__u16 tag_type;
__u16 tag_len;
char tag_data[0];
} __attribute ((packed));
又如在asterisk的源码中的Pbx.c:
struct ast_ignorepat {
const char *registrar;
struct ast_ignorepat *next;
char pattern[0];
};
结构体最后的长度为0的数组是GCC中广泛使用技巧,常用来构成可变长缓冲区。
在创建时,malloc一段结构体大小加上可变长数据长度的空间给它:malloc(sizeof(struct pppoe_tag)+ buff_len),可变长部分按数组访问方式访问;释放时,直接把整个结构体free掉就可以了。
例子如下:
struct pppoe_tag *sample_tag;
__u16 sample_tag_len = 10;
sample_tag = (struct pppoe_tag *)malloc( sizeof(struct pppoe_tag) + sizeof(char) * sample_tag_len);
sample_tag->tag_type = 0xffff;
sample_tag->tag_len = sample_tag_len;
sample_tag->tag_data[0]=….
…
释放时:
free(sample_tag)
这样的好处有两个:
一次分配解决问题,省了不少麻烦。为了防止内存泄漏,如果是分两次分配(结构体和缓冲区),那么要是第二次malloc失败了,必须回滚释放第一个分配的结构体。这样带来了编码麻烦。
其次,分配了第二个缓冲区以后,如果结构里面用的是指针,还要为这个指针赋值。同样,在free这个buffer的时候,用指针也要两次free。而且小内存的管理是非常困难的,如果用指针,这个buffer的struct部分就是小内存了,在系统内存在多了势必严重影响内存管理的性能。要是用空数组把struct和实际数据缓冲区一次分配大块问题,就没有这个问题。
所以,结构体最后使用0或1的长度数组的原因,主要是为了方便的管理内存缓冲区,如果你直接使用指针而不使用数组,那么,你在分配内存缓冲区时,就必须分配结构体一次,然后再分配结构体内的指针一次,(而此时分配的内存已经与结构体的内存不连续了,所以要分别管理即申请和释放)而如果使用数组,那么只需要一次就可以全部分配出来;反过来,释放时也是一样,使用数组,一次释放,使用指针,得先释放结构体内的指针,再释放结构体。还不能颠倒次序。
这个技巧其实就是分配一段连续的的内存,减少内存的碎片化。在Linux操作系统开发或者嵌入式开发,这种技巧尤其常见。
PS:某些编译器不支持长度为0的数组的定义,在这种情况下只要将它定义成char tag_data[1],使用方法相同。
发现柔性数组和下面一个数组之间的栈空间会多出一个16个字节的空间(64位系统),为什么呢
xx@xxx:~/c$ ./msg
sizeof(struct my_msg) = 8 , siezof(struct my_msg1)= 16
hello_msg.buf = 0x7ffff04438b8
hello_msg2.type = 0x7ffff04438a0
hello_msg.buf[0] = 0x7ffff04438b8
hello_msg.type = 0x7ffff04438b0
hello_msg2.buf = 0x7ffff04438a8
xxx@xx:~/c$ cat msg.c
#include <stdio.h>
struct my_msg {
int type;
int len;
int buf[0];
};
struct my_msg2 {
int type;
int len;
int * buf;
};
int main(int argc, char **argv) {
struct my_msg hello_msg;
struct my_msg2 hello_msg2;
printf("sizeof(struct my_msg) = %lu , siezof(struct my_msg1)= %lu \n",sizeof(hello_msg),sizeof(struct my_msg2));
printf("hello_msg.buf = %p \n", &hello_msg.buf);
printf("hello_msg2.type = %p \n", &hello_msg2.type);
printf("hello_msg.buf[0] = %p \n", &hello_msg.buf[0]);
printf("hello_msg.type = %p \n", &hello_msg.type);
printf("hello_msg2.buf = %p \n", &hello_msg2.buf);
return 0;
}
- 柔性数组 元素个数为0的数组 变长数组
- 变长(柔性)数组
- c/c++ 柔性数组 -- 结构体变长的妙用——0个元素的数组 (转载)
- 【C语言】变长数组与柔性数组
- 柔性数组成员 长度为0的数组
- 何为柔性数组
- 何为柔性数组
- C语言变长消息定义:柔性数组
- 关于元素个数为0的数组使用心得!
- 关于元素个数为0的数组use心得
- 关于元素个数为0的数组use心得
- 0元素数组实现变长TLV数据结构
- 0元素数组实现变长TLV数据结构
- 柔性数组的了解
- 柔性数组的使用
- 柔性数组
- 柔性数组!
- 柔性数组
- android 返回键监听
- Intersection of Two Linked Lists
- linux常用命令大全 初学
- qt的redo和undo undo撤销(后退),redo取消撤销(前进)
- chattr lsattr文件隐藏属性
- 柔性数组 元素个数为0的数组 变长数组
- uva live 4394 String painter 区间dp
- Object-c归档使用
- Leetcode[21]-Merge Two Sorted Lists
- CPDA项目数据分析师和CDA数据分析师有什么区别?
- chrome 突然出现 ERR_PROXY_CONNECTION_FAILED
- 第三章,设置按钮边框(Android)
- 动态链接库:相关1
- Java apache上传文件