结构体成员最后一个定义0长度数组
来源:互联网 发布:压缩软件 mac 编辑:程序博客网 时间:2024/05/17 08:25
问题:最近看IO 块设备的访问方法,其中一bio 结构体最后一个是长度为0 的数组,这个有什么意义呢?
struct bio { sector_t bi_sector; /* 磁盘上相关扇区 */ struct bio *bi_next; /* 请求列表 */ struct block_device *bi_bdev; /* 相关的块设备 */ unsigned long bi_flags; /* 状态和命令标志 */ unsigned long bi_rw; /* 读还是写 */ unsigned short bi_vcnt; /* bio_vecs的数目 */ unsigned short bi_idx; /* bio_io_vect的当前索引 */ /* Number of segments in this BIO after * physical address coalescing is performed. * 结合后的片段数目 */ unsigned int bi_phys_segments; unsigned int bi_size; /* 剩余 I/O 计数 */ /* * To keep track of the max segment size, we account for the * sizes of the first and last mergeable segments in this bio. * 第一个和最后一个可合并的段的大小 */ unsigned int bi_seg_front_size; unsigned int bi_seg_back_size; unsigned int bi_max_vecs; /* bio_vecs数目上限 */ unsigned int bi_comp_cpu; /* 结束CPU */ atomic_t bi_cnt; /* 使用计数 */ struct bio_vec *bi_io_vec; /* bio_vec 链表 */ bio_end_io_t *bi_end_io; /* I/O 完成方法 */ void *bi_private; /* bio结构体创建者的私有方法 */#if defined(CONFIG_BLK_DEV_INTEGRITY) struct bio_integrity_payload *bi_integrity; /* data integrity */#endif bio_destructor_t *bi_destructor; /* bio撤销方法 */ /* * We can inline a number of vecs at the end of the bio, to avoid * double allocations for a small number of bio_vecs. This member * MUST obviously be kept at the very end of the bio. * 内嵌在结构体末尾的 bio 向量,主要为了防止出现二次申请少量的 bio_vecs */ struct bio_vec bi_inline_vecs[0]
}
如果申请做下面的处理:
struct bio *buf;
int bio_vec_len /*缓冲区数据的长度*/
int bio_vec_len /*缓冲区数据的长度*/
/*直接把buffer的结构体跟存放数据的内存一起分配了*/
buf = (struct bio *) malloc(sizeof(struct bio) + bio_ven_len*sizeof(struct bio_vec));
buf->bio_vec = "数据struct bio_vec data\n";
/*也可以下面这样引用:*/
buf->bio_vec = “初始化数据”; /*bio_vec data的取值范围:0~bio_vec_len-1*/
在结构体中,我们定义了0长度的数组,按理buf->bio_vec =“初始化数据”;属于越界访问,但是我们把结构体后面的n*sizeof(struct bio_vec)个长度的空间也一起申请了,所以该访问是合法的!
结构体最后使用0或1的长度数组的原因,主要是为了方便的管理内存缓冲区,如果你直接使用指针而不使用数组,那么,你在分配内存缓冲区时,就必须分配结构体一次,然后再分配结构体内的指针一次,(而此时分配的内存已经与结构体的内存不连续了,所以要分别管理即申请和释放)而如果使用数组,那么只需要一次就可以全部分配出来,(见下面的例子),反过来,释放时也是一样,使用数组,一次释放,使用指针,得先释放结构体内的指针,再释放结构体。还不能颠倒次序。
其实就是分配一段连续的的内存,减少内存的碎片化。
example:
在Linux系统里,/usr/include/linux/if_pppox.h里面有这样一个结构:
struct pppoe_tag {
__u16 tag_type;
__u16 tag_len;
char tag_data[0];
} __attribute ((packed));
最后一个成员为可变长的数组,对于TLV(Type-Length-Value)形式的结构,或者其他需要变长度的结构体,用这种方式定义最好。使用起来非常方便,创建时,malloc一段结构体大小加上可变长数据长度的空间给它,可变长部分可按数组的方式访问,释放时,直接把整个结构体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)
其实就是分配一段连续的的内存,减少内存的碎片化。
example:
在Linux系统里,/usr/include/linux/if_pppox.h里面有这样一个结构:
struct pppoe_tag {
__u16 tag_type;
__u16 tag_len;
char tag_data[0];
} __attribute ((packed));
最后一个成员为可变长的数组,对于TLV(Type-Length-Value)形式的结构,或者其他需要变长度的结构体,用这种方式定义最好。使用起来非常方便,创建时,malloc一段结构体大小加上可变长数据长度的空间给它,可变长部分可按数组的方式访问,释放时,直接把整个结构体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)
更多详细网址:
http://stackoverflow.com/questions/11733981/what-is-the-purpose-of-a-zero-length-array-in-a-struct
https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
1 0
- 结构体成员最后一个定义0长度数组
- 结构体中最后一个成员为[0]或[1]长度数组(柔性数组成员)
- 1---结构体中最后一个成员为[0]长度数组的用法
- 结构体中最后一个成员为[0]或[1]长度数组(柔性数组成员)的用法
- 结构体中最后一个成员为[0]或[1]长度数组(柔性数组成员)的用法
- 结构体中最后一个成员为[0]或[1]长度数组(柔性数组成员)的用法
- 在结构体最后定义一个长度为0的字符数组(技巧)
- 在结构体最后定义一个长度为0的字符数组
- 在结构体最后定义一个长度为0的字符数组(技巧)
- 在结构体最后定义一个长度为0的字符数组(技巧)
- 在结构体最后定义一个长度为0的字符数组(技巧)
- 在结构体最后定义一个长度为0的字符数组(技巧)
- 结构体中最后一个成员数组定义0个元素的意义
- 长度为0的数组只用在结构体的最后一个成员,用以做一个地址标记,以后用。
- 长度为0的数组只用在结构体的最后一个成员,用以做一个地址标记,以后用。
- 结构体中最后成员为一个数组(长度为零)与一个指针
- 关于零长度的数组——结构体最后一个成员char[0]和char[1]
- C/C++ 学习笔记:结构体中最后一个成员为[0]或[1]长度数组(柔性数组成员)的用法
- TCP/IP协议三次握手与四次握手流程解析
- 2015-8-19省赛模拟总结
- PHP 的var const static define self $this 使用详解
- iostat和iowait详细解说(转载:http://oplinux.com/order/iostat.html)
- cocos2dx 3.x bindings-generator(Part one)
- 结构体成员最后一个定义0长度数组
- STL map 按key值和按value值排序
- VS2013中如何解决error C4996: 'fopen'问题
- 关于bat安装与卸载服务脚本
- C#中Abstract和Virtual的区别
- 获取Android的屏幕快读和高度
- iOS 博客资源精选
- Effective Objective-C 2.0 第1条:了解Objective-C语言的起源
- xxresult(28): error C2825: '_Fty': 当后面跟“::”时必须为类或命名空间