柔性数组

来源:互联网 发布:ubuntu 14.04 lts安装 编辑:程序博客网 时间:2024/04/26 17:16

 一、

incomplete tuyep:不完整类型

exgter你 char [];

 

二、

flexible array member

struct {

int data;

float fa[];

}f_str_t; c99ddD的标准ing形式

 

struct {

int data;

float fa[0];

}f_str_t; c99dd的非标准形式

 

示例:

C语言的柔性数组运用解析

分类: C语言 30人阅读 评论(0)收藏 举报
简化版应用场景:有一串不同类型,不同大小的数据需要传输,某通信协议支持x byte的数据包长度,将这一串数据封装成不大于x byte的数据包依次传输,如何设计数据包的封装和解析?

设计数据包:为了方便对端解析,设计数据包有头部和数据两段,头部用结构体的元素表示,需要什么信息则添加一个元素定义,数据段用柔性数组,是为了保证头部和数据段得内存保持连续,如下所示:

[html] view plaincopyprint?
  1. typedef struct node_s {  
  2.     int type;        /* 头部,可根据实际情况添加元素 */  
  3.     int len;         /* 头部,标识数据段已使用的长度 */  
  4.     char value[0];   /* 数据段,柔性数组 */  
  5. } node_t;  

所以,柔性数组实现扩展长度的结构体一句话概括就是:在结构体的最后加上一个长度为零的char数组

用sizeof(node_t)可以发现,柔性数组是不占内存空间的。


如何添加一段数据到数据包呢?

1,初始化:

[cpp] view plaincopyprint?
  1. #define MAX_INFO_SIZE (x - sizeof(node_t))  
[cpp] view plaincopyprint?
  1. node_t *nodeinfo;  
  2. char *mark;  
  3. node_info = (node_t *)malloc(sizeof(node_t) + MAX_INFO_SIZE);  
  4. if (node_info == NULL) {  
  5.     mem_error();  
  6. }  
[cpp] view plaincopyprint?
  1. memset(node_info, 0, sizeof(node_t) + MAX_INFO_SIZE);  
  2. node_info->type = your_type;  
  3. node_info->len = 0;  
  4. mark = &node_info->value;  


即是:申请一段内存,初始化,将数据段的标志位mark指向value地址,还没有添加数据,所以len为0;

2,添加数据

[cpp] view plaincopyprint?
  1. for (data = x; data < y; data = next(x)) { /* 遍历那串数据,简化版 */  
  2.     len = get_data_len(data);  
  3.     if (node_info->len + len <= MAX_INFO_SIZE) {  
  4.         memcpy(mark, data, len);  
  5.         mark += len;  
  6.         node_info->len += len;  
  7.     } else {  
  8.         send(node_info); <span style="white-space:pre">           </span>/* 调用某协议发送出数据,简化版 */  
  9.   
  10.         memset(node_info, 0, sizeof(node_t) + MAX_INFO_SIZE);  
  11.         node_info->type = your_type;  
  12.         node_info->len = 0;  
  13.         mark = &node_info->value;  
  14.         memcpy(mark, data, len);  
  15.         mark += len;  
  16.         node_info->len += len;   
  17.     }  
  18. }  
  19. send(node_info); <span style="white-space:pre">               </span>/* 发送最后一个数据包 */  


添加数据的操作即是:将数据拷贝到数据段,记录添加的长度,移动标记位以便下次添加。如果数据达到数据包最大值,发送掉这个包,然后继续添加操作。

这样,每个不大于x byte的数据包都填充好了data数据,并且利用通信机制发送到了另一个地方。

那“另一个地方”接收到了这个不大于x byte的数据包,如何从数据包里解析出data数据来呢?

3,解析数据

假设某台机器得到了这个数据包,要查看数据包里每个data的内容,如何解析?

[cpp] view plaincopyprint?
  1. node_t *node_info;  
  2. char *buf;  
  3. int len;  
  4. node_t *node_info;  
  5. get_info(node_info);         /* 让node_info得到了那个不大于x byte的数据包,简化版 */  
  6. for (buf = node_info->value; buf < node_info->value + node_info->len; buf += len) {  
  7.     data = (data_t *)buf;    /* 从数据包里取到了一个data */  
  8.     op(data);                /* 查看数据包,简化版 */  
  9.     len = get_data_len(data);   
  10. }  


以上,利用柔性数组构造一个数据包,并进行封包,发包,解包的操作就完成了!

在实际生产应用中,要对数据包的头部扩展,其他的每一个操作都不会像例子的伪代码那样简单,但原理是一样的。


如果没有用过柔性数组的童鞋,可以思考一下:

为什么最后一个原始是0元素的数组而不是指针呢?假如不是C99怎么办?


---------------------------------这是分割线-------------------------------------

第一次写博客,实在不知道写什么东西,也发现即使是自己经常用,已经习以为常的小知识点,要用文字阐述清除,也是非常困难滴,文中肯定有很多不足,欢迎大家指正!

 

 

 

ji结构体重中最后一个成员为未知大小的数组,叫做柔性数组成员。

c99标准之后,才支持该语法。