变长结构体的应用
2016-02-29 22:30
309 查看
顾名思义,结构体长度是“可变”的。但是这个可变不针对sizeof()函数。
用例代码:
打印输出:
总结:sizeof看结构体,只有实体数据和指针占空间,char array[0]是不占长度的。
变长结构体的0长度数组有两种声明方法(见S1和S2),不影响sizeof()对结构体大小的判断。
变长结构体S1与S2是为了达到和S3相同的效果而生的,具体内容的访问上也有些类似。
应用上,必须用堆空间,指针的应用也很巧妙,指向紧跟结构体数组的位置。至于后边的为什么能用,因为后边空间是malloc或new来的一大片连续空间的一部分。
如果堆空间的申请/销毁的资源开支大与效率低是个劣势的话,可能优势就在于和S3的二次申请/销毁比,开支还会小点。这样选择也肯定是非这么用不可的时候了。比如我要接动态的数据,打包并发送,数据包的头部分肯定是固定的,但是尾部,内容具体有多长不确定,如果都以最大长度来申请,会很耗费内存。
struct s* ps = malloc(sizeof(struct S)+strlen(string1));//比如是字符串,有了变长结构体,我就我就能strlen()一下获取长度,再去申请合适的空间
有一个问题无解,sizeof()结构体是固定长度,sizeof()对象都是多长?因为动态申请时你只拿到了指针,所以看不到对象长度,只能看到4(32位机)。
注意:据说,按理说也是,如果用S3,必须先释放array的空间,再释放S3结构体对象的空间。但是感觉上顺序颠倒也能行,这是因为删除数据的原则只是不再用,而不是去改变内存具体的电容存储内容,巧合罢了,但是很危险,属于越界行为。如果是动态运行,应该就会出错了(不过在另一个blog中我在linux gcc的爆堆实验没怎么成功,就是说,即使free过,也会耗尽资源,总之不能重复涂抹一处空间)
===========================================
以前IM的项目里别人的代码中,有个用法,感觉是错误的,至少不是变长结构体的用法,也许是重用名的用法?创建一个别名!也许是不懂变长结构体,迭代的时候胡乱修改,成这样了。这个结构体的长度是36==16+6+6+4,0长度数组的特性还在,倒是可以实现一个成员的重命名功能,也许真是为了干这个的,不过就是提醒一下,零长度数组必须放到末尾才能起到变长结构体的效果,并且必须是动态申请的堆空间。动态申请的你只能用指针访问,所以也无从获取对象长度,所以要谨慎判断变长结构体的边界。
下面演示一下别名(Nickname)的用法:
用例代码:
//弹性数组的大小,各对象是否都不一样? //如果都一样,怎么看空间大小,用sizeof array来加? //但是如果是对象,也没法看,因为是指针指向对象的形式 //用的时候,申请可以是这样 #include<malloc.h> #define ARRAY_SIZE 200 struct S{ int* a; int *b; char array[0]; }; struct S2{ int* a; int *b; char array[];//另一种更稳妥的形式,而前者可能编译报错 }; struct S3{ int a; char *array; }; int main(){ struct S* p = (struct S*)malloc(100); strcpy(p->array,"hello"); printf("struct's size %d\n",sizeof(struct S)); printf("strict pointer's size:%d\n",sizeof(p)); printf("sizeof array : %d\n",sizeof(p->array)); printf("strlen array: %d\n",strlen(p->array)); printf("%s\n",p->array); //用的时候,申请可以是这样 struct S* p2 = (struct S*)malloc(sizeof(struct S) + ARRAY_SIZE); struct S2* pS2 = (struct S2*)malloc(sizeof(struct S2) + ARRAY_SIZE); strcpy(p2->array,"hello"); printf("struct's size %d\n",sizeof(struct S2)); printf("strict pointer's size:%d\n",sizeof(p2)); printf("sizeof array : %d\n",sizeof(p2->array)); printf("strlen array: %d\n",strlen(p2->array)); printf("%s\n",p->array); struct S3* p3 = (struct S3*)malloc(sizeof(struct S3)); p3->array = (char *)malloc(ARRAY_SIZE); strcpy(p3->array,"hello world"); printf("p3->array:%s\n",p3->array); //free(p3->array); //改变顺序运行也不报错,给free传参就不算访问了? //p3已经free了,还能访问p3->array? free(p3); printf("p3->array:%s\n",p3->array); free(p3->array); //访问其实都能访问,就是不确保对了吧 printf("p3->array:%s\n",p3->array); }
打印输出:
struct's size 8 strict pointer's size:4 sizeof array : 0 strlen array: 5 hello struct's size 8 strict pointer's size:4 sizeof array : 0 strlen array: 5 hello p3->array:hello world p3->array:hello world p3->array:hello world
总结:sizeof看结构体,只有实体数据和指针占空间,char array[0]是不占长度的。
变长结构体的0长度数组有两种声明方法(见S1和S2),不影响sizeof()对结构体大小的判断。
变长结构体S1与S2是为了达到和S3相同的效果而生的,具体内容的访问上也有些类似。
应用上,必须用堆空间,指针的应用也很巧妙,指向紧跟结构体数组的位置。至于后边的为什么能用,因为后边空间是malloc或new来的一大片连续空间的一部分。
如果堆空间的申请/销毁的资源开支大与效率低是个劣势的话,可能优势就在于和S3的二次申请/销毁比,开支还会小点。这样选择也肯定是非这么用不可的时候了。比如我要接动态的数据,打包并发送,数据包的头部分肯定是固定的,但是尾部,内容具体有多长不确定,如果都以最大长度来申请,会很耗费内存。
struct s* ps = malloc(sizeof(struct S)+strlen(string1));//比如是字符串,有了变长结构体,我就我就能strlen()一下获取长度,再去申请合适的空间
有一个问题无解,sizeof()结构体是固定长度,sizeof()对象都是多长?因为动态申请时你只拿到了指针,所以看不到对象长度,只能看到4(32位机)。
注意:据说,按理说也是,如果用S3,必须先释放array的空间,再释放S3结构体对象的空间。但是感觉上顺序颠倒也能行,这是因为删除数据的原则只是不再用,而不是去改变内存具体的电容存储内容,巧合罢了,但是很危险,属于越界行为。如果是动态运行,应该就会出错了(不过在另一个blog中我在linux gcc的爆堆实验没怎么成功,就是说,即使free过,也会耗尽资源,总之不能重复涂抹一处空间)
===========================================
以前IM的项目里别人的代码中,有个用法,感觉是错误的,至少不是变长结构体的用法,也许是重用名的用法?创建一个别名!也许是不懂变长结构体,迭代的时候胡乱修改,成这样了。这个结构体的长度是36==16+6+6+4,0长度数组的特性还在,倒是可以实现一个成员的重命名功能,也许真是为了干这个的,不过就是提醒一下,零长度数组必须放到末尾才能起到变长结构体的效果,并且必须是动态申请的堆空间。动态申请的你只能用指针访问,所以也无从获取对象长度,所以要谨慎判断变长结构体的边界。
// 注册 typedef struct { long long m_llUserId; // 用户名 char m_pcPsw[0]; // 密码 char ShamPsw[16]; // 忽略 char m_pcVerCode[0]; // 验证码 char ShamVerCode[6]; // 忽略 char m_pcCode[0]; // 邀请码 char ShamCode[6]; // 忽略 }TRegisterData;
下面演示一下别名(Nickname)的用法:
#include<stdio.h> #include<malloc.h> #define ARRAY_SIZE 200 struct S2{ int* a; int *b; //char arrayNickname[];//不写0的话,定义非变长结构体时编译不过去 char arrayNickname[0];//更稳妥的写法 char array[18]; }; int main(){ struct S2* pS2 = (struct S2*)malloc(sizeof(struct S2) + ARRAY_SIZE); strcpy(pS2->array,"hello"); printf("struct's size %d\n",sizeof(struct S2)); printf("strict pointer's size:%d\n",sizeof(pS2)); printf("sizeof arrayNickname : %d\n",sizeof(pS2->arrayNickname)); printf("strlen arrayNickname: %d\n",strlen(pS2->arrayNickname)); printf("array:%s\n",pS2->array); printf("arrayNickname:%s\n",pS2->arrayNickname); }
struct's size 28 strict pointer's size:4 sizeof arrayNickname : 0 strlen arrayNickname: 5 array:hello arrayNickname:hello
相关文章推荐
- 二级域名原理以及程序
- 一根网线内的8根线哪4根是传输数据的,哪四根是防干扰的
- TCP三次握手及原理
- jQuery中的pushStack实现原理和应用实例
- sqlserver索引的原理及索引建立的注意事项小结
- php中的ini配置原理详解
- jquery原理以及学习技巧介绍
- PHP strtotime函数用法、实现原理和源码分析
- Base64编码解码原理及C#编程实例
- IsPostBack原理的介绍
- jQuery中noconflict函数的实现原理分解
- MySQL主从同步原理介绍
- 关于Ajax技术原理的3点总结
- 谈谈Ajax原理实现过程
- ajax 技术和原理分析
- 路由器原理及路由协议
- Oracle数据块实现原理深入解读
- Geohash的原理、算法和具体应用探究
- PHP的运行机制与原理(底层)
- 4种VPS主机技术原理及优缺点(VPS独享主机技术原理)