在标准C和C++中0长数组如charArray[0]是不允许使用的,因为这从语义逻辑上看,是完全没有意义的。
但是,GUN中却允许使用,而且,很多时候,应用在了变长结构体中,如:
StructPacket
{
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);发送数据
- 浏览: 549584 次
- 性别:
- 来自: 上海
-
文章分类
- 全部博客 (231)
- 一个操作系统的实现 (20)
- 汇编(NASM) (12)
- Linux编程 (11)
- 项目管理 (4)
- 计算机网络 (8)
- 设计模式(抽象&封装) (17)
- 数据结构和算法 (32)
- java基础 (6)
- UML细节 (2)
- C/C++ (31)
- Windows (2)
- 乱七八糟 (13)
- MyLaB (6)
- 系统程序员-成长计划 (8)
- POJ部分题目 (10)
- 数学 (6)
- 分布式 & 云计算 (2)
- python (13)
- 面试 (1)
- 链接、装载与库 (11)
- java并行编程 (3)
- 数据库 (0)
- 体系结构 (3)
- C++ template / STL (4)
- Linux环境和脚本 (6)
最新评论
-
chuanwang66:
默默水塘 写道typedef void(*Fun)(void) ...
C++虚函数表(转) -
默默水塘:
typedef void(*Fun)(void);
C++虚函数表(转) -
lishaoqingmn:
写的很好,例子简单明了,将观察者模式都表达了出来。
这里是ja ...
观察者模式——Observer
发表评论
-
C++引用计数
2013-12-29 14:48 1203主要参考《提高C++性能的编程技术》第12章 引用计数 ... -
string.h(二)C的字符串分隔函数strtok()
2013-12-19 13:25 1542char *strtok(char *str1, c ... -
关于size_t 和 ptrdiff_t 【转】
2013-12-12 18:57 886Abstract Introduction size ... -
new, operator new 和 placement new
2013-12-12 17:08 1098一、new 和 delete 的过程: 在进行一切讲解之 ... -
填充与对齐——指定变量的地址偏移【转】
2013-11-08 14:53 886转自 http://hi.baidu.com/bai_ye ... -
数组和指针并不同(总结《C专家编程chap4》)
2013-10-06 14:55 963左值(地址)和右值(地址的内容): 1. 使用数组 ... -
细说C++全局变量、局部变量和静态局部变量【转】
2013-08-15 17:17 881转自http://see.xidian.ed ... -
strcpy和strncpy用法和区别(转)
2013-07-31 17:37 31strcpy和strncpy用法和区别 转自:http ... -
stl iterator&const_iterator
2013-07-11 09:38 14iterator和const_iterator访问conta ... -
C++类对象创建过程揭密(转载)
2013-05-24 16:56 945转载:http://blog.csdn.net ... -
C调用汇编
2013-03-27 20:28 1472一、汇编语言的两种语法格式 Intel格式: 大 ... -
C++四个类型转换关键字const_cast, static_cast, dynamic_cast, reinterpret_cast
2013-02-27 10:13 2551C风格的强制类型转换( ... -
C/C++中内存模型
2012-12-30 11:07 1646一直以来,C++ ... -
map使用
2012-12-29 15:21 35需要#include <map> 定义map& ... -
C++调用C
2012-11-29 22:42 1294一般地,C++调用C有两种形式(网上资料一般没讲全): ... -
关于计算精度
2012-11-22 14:53 907本文是Sam我总结的,在C++学习过程中常见的一些涉及 ... -
C++随机数
2012-11-07 19:41 939C++随机数 #include<iostream ... -
C文件操作(一)
2012-11-07 19:11 1638C文件操作(流式文件 &a ... -
C++中的内联函数inline
2012-07-13 19:16 1087在c++中,为了解决一些频繁调用的小函数大量消耗栈空间或者 ... -
模板和泛型编程???从P269继续
2012-04-22 09:58 859参考书 <C++ By Dissection> ...
相关推荐
柔性数组(Flexible Array Member)是C++中一种特殊的数据结构设计,主要应用于结构体或类的设计,以提高内存效率和程序的灵活性。在C++标准库中,它被广泛用于容器如`std::vector`、`std::string`等内部实现。在本...
本文实例分析了C语言柔性数组的概念及用法,对于进一步学习C程序设计有一定的借鉴价值。分享给大家供大家参考。具体如下: 一般来说,结构中最后一个元素允许是未知大小的数组,这个数组就是柔性数组。但结构中的...
总结来说,通过使用柔性数组来动态管理内存大小,利用智能指针(如`std::unique_ptr`)来自动管理内存生命周期,以及采用内置容器(如`std::vector`)来替代裸数组,我们可以有效地预防C++编程中的内存操作问题,...
C99标准的引入,带来了诸如复数类型、变量长度数组、内联函数、柔性数组成员等新特性。书中对此进行了详细解读,让读者能够充分利用这些新功能,编写更高效、更灵活的代码。 总的来说,《C语言参考手册_第五版_邱...
14. **标准C99与C11**:介绍新标准引入的特性,如复数类型、柔性数组成员、新的内存管理函数等。 15. **C语言的局限性与现代编程语言的对比**:讨论C语言的性能优势与安全问题,以及与C++、C#、Java等语言的异同。 ...
- **柔性数组**:允许在结构体末尾定义一个未知长度的数组。 - **struct与class的区别**:在C++中,`struct`默认成员权限为public,而`class`默认为private。 **1.16 union关键字** - **大小端模式对union类型数据...