转自C/C++ 中的0长数组(柔性数组)

在标准C和C++中0长数组如charArray[0]是不允许使用的,因为这从语义逻辑上看,是完全没有意义的。但是,GUN中却允许使用,而且,很多时候,应用在了变长结构体中,如:

struct Packet
{
int state;
int len;
char cData[0]; //这里的0长结构体就为变长结构体提供了非常好的支持
};

首先对0长数组做一个解释:

用途 :长度为0的数组的主要用途是为了满足需要变长度的结构体。

用法 :在一个结构体的最后 ,申明一个长度为0的数组,就可以使得这个结构体是可变长的。对于编译器来说,此时长度为0的数组并不占用空间,因为数组名本身不占空间,它只是一个偏移量, 数组名这个符号本身代 表了一个不可修改的地址常量 (注意:数组名永远都不会是指针! ),但对于这个数组的大小,我们可以进行动态分配。请仔细理解后半部分,对于编译器而言,数组名仅仅是一个符号,它不会占用任何空间,它在结构体中,只是代表了一个偏移量,代表一个不可修改的地址常量!

 

对于0长数组的这个特点,很容易构造出变长结构体,如缓冲区,数据包等等:

struct Buffer
{
int len;
char cData[0];
};

这样的变长数组常用于网络通信中构造不定长数据包,不会浪费空间浪费网络流量,比如我要发送1024字节的数据,如果用定长包,假设定长包的长度为2048,就会浪费1024个字节的空间,也会造成不必要的流量浪费。

struct packet
{
char data[2048];
}
packet p;
memcpy(p.data,"1024 datas.........",1024)
send(socket,(char*)&p,sizeof(p));

由于考虑到数据的溢出,变长数据包中的data数组长度一般会设置得足够长足以容纳最大的数据,因此packet中的data数组很多情况下都没有填满数据,因此造成了浪费,而如果我们用变长数组来进行封包的话,就不会造成浪费(最多会造成4个字节的浪费,包头的int型的len不属于数据因此算是浪费),如前面的Buffer结构体,假如我们要发送1024个字节,我们如何构造这个数据包呢:

char *tmp = (char*)malloc(sizeof(Buffer)+1024)

这句代码的作用是申请一块连续的内存空间,这块内存空间的长度是Buffer的大小加上1024数据的大小,由两部分构成,sizeof(Buffer)和1024,如果仔细观察的话,会发现这种申请方法比第一种多了一段sizeof(Buffer)大小的空间,原因何在?如下

Buffer *p = (Buffer*)tmp;
p->len = 1024;
memcpy(p.cData,"1024 datas............",1024);

如上三行代码,首先做一个强制类型转换,Buffer类型的指针指向内存的起始位置,这段内存要分两部分使用,前部分4个字节p->len,作为包头(就是多出来的那部分),这个包头是用来描述紧接着包头后面的数据部分的长度,这里是1024,所以前四个字节赋值为1024(既然我们要构造不定长数据包,那么这个包到底有多长呢,因此,我们就必须通过一个变量来表明这个数据包的长度,这就是len的作用),而紧接其后的内存是真正的数据部分,通过p->cData定位到该部分的起始地址,最后,进行一个memcpy()内存拷贝,把要发送的数据填入到这段内存当中,最后:

send(socket,p,sizeof(Buffer)+1024);发送数据

C/C++ 中的0长数组(柔性数组)的更多相关文章

  1. 柔性数组(Redis源码学习)

    柔性数组(Redis源码学习) 1. 问题背景 在阅读Redis源码中的字符串有如下结构,在sizeof(struct sdshdr)得到结果为8,在后续内存申请和计算中也用到.其实在工作中有遇到过这 ...

  2. flexible array柔性数组、不定长的数据结构Struct详解

    柔性数组,这个名词对我来说算是比较新颖的,在学习跳跃表的实现时看到的.这么好听的名字,的背后到底是如何的优雅. 柔性数组,其名称的独特和迷惑之处在于“柔性”这个词.在C/C++中定义数组,是一个定长的 ...

  3. gcc 0长数组学习

    首先,我们要知道,0长度的数组在ISO C和C++的规格说明书中是不允许的.这也就是为什么在VC++2012下编译你会得到一个警告:“warning C4200: 使用了非标准扩展 : 结构/联合中的 ...

  4. C语言0长度数组(柔性数组)

    0长度数组,又称为柔性数组(flexible array).通经常使用来实现变长数组.常见于TLV(type-length-value)的数据结构中. 在标准 C 和 C++ 中,不同意用 0 长度数 ...

  5. 深入浅出C语言中的柔性数组

    在日常的编程中,有时候需要在结构体中存放一个长度动态的字符串,一般的做法,是在结构体中定义一个指针成员,这个指针成员指向该字符串所在的动态内存空间,例如: typedef struct test { ...

  6. POJ-3294-Life Forms(后缀数组-不小于 k 个字符串中的最长子串)

    题意: 给定 n 个字符串,求出现在不小于 k 个字符串中的最长子串. 分析: 将 n 个字符串连起来,中间用不相同的且没有出现在字符串中的字符隔开,求后缀数组. 然后二分答案,将后缀分成若干组,判断 ...

  7. poj 3294 后缀数组 多字符串中不小于 k 个字符串中的最长子串

    Life Forms Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 16223   Accepted: 4763 Descr ...

  8. [C/C++] char data[0](柔性数组)

    转自:http://blog.csdn.net/yby4769250/article/details/7294696 在标准C和C++中0长数组如charArray[0]是不允许使用的,因为这从语义逻 ...

  9. int main (int argc, const char * argv[0]) 中参数的含义;指针数组和数组指针

    恩,有的编译器初始化时候会产生这样的参数 argc是命令行总的参数个数,argv[]是argc个参数,其中第0个参数是程序的全名 1. 几种C++ 常见的参数种类 int main(void); in ...

随机推荐

  1. oracle12 pl/sql

    pl/sql块介绍 介绍   块(block)是pl/sql的基本程序单元,编写pl/sql程序实际上就是编写pl/sql块,要完成相对简单的应用功能,可能只需要编写一个pl/sql块,但是如果想要实 ...

  2. 【转】cocos2d-x学习笔记03:绘制基本图元

    第一部分:基本图形绘制 cocos2dx封装了大量opengl函数,用于快速绘制基本图形,这些代码的例子在,tests\DrawPrimitivesTest目录下 注意,该方法是重载node的draw ...

  3. 项目FAQ

    报错: Conversion from String Literal to Char* is deprecated http://stackoverflow.com/questions/1369030 ...

  4. asp.net网站性能优化2则

    摘要:Web服务器的性能优化有很多资料介绍了,多台主机负载均衡,查询结果的多级缓 存,数据库索引优化等都是常见的优化手段.随着后端优化空间越来越小,现在越来越多 的网站更注重前端性能的优化,就是浏览器 ...

  5. iis6配置使用页面Gzip压缩提速

    iis7默认就启用了Gzip压缩,节约带宽,流量,能够很明显的提升访问速度,但是iis6则没有,本文就是介绍如何通过配置开启iis6的Gzip压缩 一. HTTP压缩概述 HTTP压缩是在Web服务器 ...

  6. RedHat7搭建MongoDB集群

    下载RPM安装包# wget -c -r -N -np -nd -L -nH https://repo.mongodb.org/yum/redhat/7/mongodb-org/stable/x86_ ...

  7. Ubuntu安装sar出错Please check if data collecting is enabled in /etc/default/sysstat

    1.安装sysstat apt-get install sysstat 2.安装后无法使用: Cannot open /var/log/sysstat/sa02: No such file or di ...

  8. css height:100%失效

    有时做移动端页面时,需要用到height:100%来控制,但是设置完后会发现,用百分比的高是不生效的. 经过上网浏览等查阅资料得知,是否可以使用百分比是根据父级对象定义的.所以解决方法就是在body和 ...

  9. C# 实现的多线程异步Socket数据包接收器框架

    转载自Csdn : http://blog.csdn.net/jubao_liang/article/details/4005438 几天前在博问中看到一个C# Socket问题,就想到笔者2004年 ...

  10. hibernate 连接 oracle数据库

    前言:以下所有的操作都是基于你已经成功安装了oracle数据库并且java的开发环境正常的情况下进行的. 如果没有完善请先配置基础环境. 第一步:配置需要的环境(下载并导入需要的包). 我的百度云盘里 ...