char data[0]问题
来源:互联网 发布:android 网络配置文件 编辑:程序博客网 时间:2024/06/05 04:21
问题:当进行内存管理时,经常需要一个额外的结构,例如
struct MyData
{
char*data; // 指向分配的内存空间
intlen; // 记录空间大小
};
这样,需要进行四步操作,先分配MyData结构体,再分配要管理的内存,再让data指针指向该内存空间,再把空间大小赋给len。问题,该结构在64位系统上sizeof结果是多少?可以修改结构体的情况下有什么办法能够减少操作?
这实际上是有关char data[0]的问题。
struct MyData
{
int len;
char data[0]; // 一定是结构体的最后一个字段,且前面必须有其他字段
};
在结构中,data是一个数组名;但该数组没有元素;由于数组没有元素,该数组在该结构体中不占用空间,所以sizeof(struct Mydata) = 4,这不同于char* data,要占用一个指针的大小(32位系统下4字节,64位系统8字节)。该数组的真实地址紧随结构体MyData之后,而这个地址就是结构体后面数据的地址(如果给这个结构体分配的内容大于这个结构体实际大小,后面多余的部分就是这个data的内容);这种声明方法可以巧妙的实现C语言里的数组扩展。
使用:
struct MyData *p = (struct MyData *)malloc(sizeof(struct MyData)+strlen(str))
这样就可以通过p->data 来操作这个str。
这是个广泛使用的常见技巧,常用来构成缓冲区。比起指针,用空数组有这样的优势:
1.不需要初始化,数组名直接就是所在的偏移;
2.不占任何空间,指针需要占用空间;
3.结构体和内存可以一起分配,连续空间。
一次分配解决问题,省了不少麻烦。大家知道为了防止内存泄漏,如果是分两次分配(结构体和缓冲区),那么要是第二次malloc失败了,必须回滚释放第一个分配的结构体。这样带来了编码麻烦。其次,分配了第二个缓冲区以后,如果结构里面用的是指针,还要为这个指针赋值。同样,在free这个buffer的时候,用指针也要两次free。如果用空数组,所有问题一次解决。
其次,大家知道小内存的管理是非常困难的,如果用指针,这个buffer的struct部分就是小内存了,在系统内存在多了势必严重影响内存管理的性能。要是用空数组把struct和实际数据缓冲区一次分配大块问题,就没有这个问题。
补充说明:
char data[0]柔性数组,只能放在struct末尾,表示该struct是可变长度的,多余的容量分配给data数组,实现可变长度的数组。
在早期有些技术牛人都爱这样写,不过在今天这是一种不安全的写法,不推荐,不要指望在所有的编译器上都能得到比想要的结果。
char data[0]是否合法?
ISO/IEC 9899-1999里面,这么写是非法的,这个仅仅是GNU C的扩展,gcc可以允许这一语法现象的存在。
结构体最后使用0或1的长度数组的原因,主要是为了方便的管理内存缓冲区,如果你直接使用指针而不使用数组,那么,你在分配内存缓冲区时,就必须分配结构体一次,然后再分配结构体内的指针一次,(而此时分配的内存已经与结构体的内存不连续了,所以要分别管理即申请和释放)而如果使用数组,那么只需要一次就可以全部分配出来,(见下面的例子),反过来,释放时也是一样,使用数组,一次释放,使用指针,得先释放结构体内的指针,再释放结构体。还不能颠倒次序。
其实就是分配一段连续的的内存,减少内存的碎片化。
这个仅仅是在C99没有出台的情况下,gcc为了使用类似于C99 flexible array member而做出的一个work-around,但是现在C99出现了,并且正式支持了flexiblearray member的语法,这样的一个GNU C扩展就有点显得不合时宜了……按照ISO/IEC 9899-1999的要求,flexible array member的定义应当是这样:
struct foo
{
int variable;
char bar[ ]; // here!!!! this is the C99 flexible arraymember
};
这个才是符合标准要求的写法,当你的代码需要跨平台、跨编译器移植,并且需要这个特性的时候,这个才是唯一准确的写法!
C99中,允许结构中的最后一个成员可以是未知大小的数组(结构中,在该数组之前必须至少有一个其他成员),这被称为 flexible array member。由sizeof返回的结构的大小不包括 flexible array member的大小。
- char data[0]问题
- char data[0]用法总结
- char data[0]用法总结
- char data[0]用法总结
- char data[0]用法总结
- char data[0] 用法及意义
- 类体内的char data[0]
- char data[0]在struct末尾的用法
- 在结构体中定义char data[0]的用法
- (char)0X03的问题
- 【Java】new String(char value[]) valueOf(char data[])
- 这些怎么区别?(*(char **(*)(char **,char **))0)(char **,char **)
- C语言变长数组 struct中char data[0]的用法
- C语言变长数组 struct中char data[0]的用法
- C语言变长数组 struct中char data[0]的用法
- C语言变长数组 struct中char data[0]的用法
- C 语言变长数组 struct 中 char data[0] 的用法
- C语言变长数组 struct中char data[0]的用法
- 线性微分方程解的性质与结构
- spring数据源切换
- IDEA常用快捷键
- openfire插件开发
- 学习日记-解决PHP时间戳中月份、日期前带不带0的问题
- char data[0]问题
- 前端性能优化(Application Cache篇)
- c++文件操作
- ocilib
- c#实现16进制和字符串之间转换的代码
- CodeGenerator
- 从Android到Swift iOS开发:语言与框架对比
- 设计模式(15)-Memento 备忘录模式
- [vim] 多窗口功能