深入浅出变长结构体
深入浅出变长结构体
1、 问题的引出
项目中用到数据包的处理,但包的大小是不固定的,其长度由包头的2字节决定。比如如下的包头:88 0f 0a ob cd ef 23 00 。长度由头2个字节880f决定,考虑字节序,转为0f88,转为10进制3976个字节的包长度。
这个时候存储包的时候,一方面可以考虑设定包的大小固定:如4K=4*1024=4096个字节,因为最大包长不可能超过4k,但该方法的有缺陷,存在一种极端就是包最小仅含包头不含数据域,此时包为8个字节,浪费了4096-8 =4088个字节的存储空间。另一方面考虑有没有一种方法能根据长度进行存储,或者说初始不分配长度,计算出了长度后再分配存储呢。而实际项目中正是通过包头计算出了包的整体大小的。
这就引出了变长结构体的概念。
2、 什么叫变长结构体?
如下所示:
运行结果如下:
对比结果,我们能发现:
<1> 存储大小方面:s_two的存储较s_one、s_three都要少,[0]的好处,即用指针的方式需要多开辟存储空间的。
<2> 数据连续存储方面:s_one明显数据域是单独开辟的空间,与前的nsize不在连续的存储区域,而s_two,s_three则在连续的存储空间下。
<3>释放内存方面:显然s_one的指针的方式,需要先释放数据域部分,才能释放指向结构体的指针变量;而s_two,s_three可以直接释放。
总结如下:
结构体最后使用0或1的长度数组的原因,主要是为了方便的管理内存缓冲区,如果你直接使用指针而不使用数组,那么,你在分配内存缓冲区时,就必须分配结构体一次,然后再分配结构体内的指针一次,(而此时分配的内存已经与结构体的内存不连续了,所以要分别管理即申请和释放)。
而如果使用数组,那么只需要一次就可以全部分配出来,反过来,释放时也是一样,使用数组,一次释放,使用指针,得先释放结构体内的指针,再释放结构体。还不能颠倒次序。
其实变长结构体就是分配一段连续的的内存,减少内存的碎片化,简化内存的管理。
4、变长结构体的应用
<1>Socket通信数据包的传输;
<2>解析数据包,如笔者遇到的问题。
<3>其他可以节省空间,连续存储的地方等。
未尽事宜,后续补上……
2013/9/22pm21:36思于家中床前