变长结构体的应用
来源:互联网 发布:如何编写抢购软件 编辑:程序博客网 时间:2024/05/22 07:53
顾名思义,结构体长度是“可变”的。但是这个可变不针对sizeof()函数。
用例代码:
//弹性数组的大小,各对象是否都不一样?//如果都一样,怎么看空间大小,用sizeof array来加?//但是如果是对象,也没法看,因为是指针指向对象的形式//用的时候,申请可以是这样#include<malloc.h>#define ARRAY_SIZE 200struct 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 8strict pointer's size:4sizeof array : 0strlen array: 5hellostruct's size 8strict pointer's size:4sizeof array : 0strlen array: 5hellop3->array:hello worldp3->array:hello worldp3->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 200struct 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 28strict pointer's size:4sizeof arrayNickname : 0strlen arrayNickname: 5array:helloarrayNickname:hello
- 变长结构体的应用
- 变长结构体的实现
- 变长结构体的用法
- 变长结构体的使用
- 变长结构体的几种方法
- 变长结构体的表示方法
- 变长结构体的表示方法
- 如何定义变长的TLV结构体?
- 变长结构体
- 变长结构体
- 变长结构体
- 变长结构体
- 变长结构体
- 深入浅出变长结构体
- 深入浅出变长结构体
- 变长结构体
- SOCKET 变长结构体
- 变长数组的应用
- MySQL学习笔记2(操作数据库)
- Objective-C 和 Core Foundation 对象相互转换内存管理
- Android之SurfaceView使用总结
- UIWebView 实现自适应高度
- 算法导论学习笔记(一)排序算法之计数排序
- 变长结构体的应用
- Cpp_异常处理
- USACO 6.4.2 Electric Fences 数学+暴力
- Oracle Redo Log 机制 小结
- tcp/ip基础(一)
- 数据流分析的局限性
- jQuery小练习
- ACM路上的一大失误
- QTCreator 生成可执行程序不能运行的问题