c++柔性数组是什么

发布时间:2022-03-17 13:43:39 作者:iii
来源:亿速云 阅读:157

这篇文章主要介绍“c++柔性数组是什么”,在日常操作中,相信很多人在c++柔性数组是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”c++柔性数组是什么”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

1 引言

定长数组包

在平时的开发中,缓冲区数据收发时,如果采用缓冲区定长包,假定大小是 1k,MAX_LENGTH 为 1024。结构体如下:

//  定长缓冲区
struct max_buffer
{
    int   len;
    char  data[MAX_LENGTH];
};

数据结构的大小 >= sizeof(int) + sizeof(char) * MAX_LENGTH为了防止数据溢出的情况,data 的长度一般会设置得足够大,但也正是因为这样,才会导致数组的冗余。

假如发送 512 字节的数据,  就会浪费 512 个字节的空间, 平时通信时,大多数是心跳包,大小远远小于 1024,除了浪费空间还消耗很多流量。

内存申请:

if ((m_buffer = (struct max_buffer *)malloc(sizeof(struct max_buffer))) != NULL)
{
    m_buffer->len = CUR_LENGTH;
    memcpy(m_buffer->data, "max_buffer test", CUR_LENGTH);
    printf("%d, %s\n", m_buffer->len, m_buffer->data);
}
 

内存释放:

free(m_buffer);
m_buffer = NULL;

指针数据包

为了避免空间上的浪费,我们可以将上面的长度为 MAX_LENGTH 的定长数组换为指针, 每次使用时动态的开辟 CUR_LENGTH 大小的空间。数据包结构体定义:

struct point_buffer
{
    int   len;
    char  *data;
};

数据结构大小 >= sizeof(int) + sizeof(char *)但在内存分配时,需要两步进行:

内存申请:

if ((p_buffer = (struct point_buffer *)malloc(sizeof(struct point_buffer))) != NULL)
{
    p_buffer->len = CUR_LENGTH;
    if ((p_buffer->data = (char *)malloc(sizeof(char) * CUR_LENGTH)) != NULL)
    {
        memcpy(p_buffer->data, "point_buffer test", CUR_LENGTH);
        printf("%d, %s\n", p_buffer->len, p_buffer->data);
    }
}
 

内存释放:

free(p_buffer->data);
free(p_buffer);
p_buffer = NULL;

虽然这样能够节约内存,但是两次分配的内存是不连续的, 需要分别对其进行管理,导致的问题就是需要对结构体和数据分别申请和释放内存,这样对于程序员来说无疑是一个灾难,因为这样很容易导致遗忘释放内存造成内存泄露。

有没有更好的方法呢?那就是今天的主题柔性数组。 

2 柔性数组 

什么是柔性数组?

柔性数组成员(flexible array member)也叫伸缩性数组成员,这种代码结构产生于对动态结构体的需求。在日常的编程中,有时候需要在结构体中存放一个长度动态的字符串,鉴于这种代码结构所产生的重要作用,C99 甚至把它收入了标准中:

As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member.

柔性数组是 C99 标准引入的特性,所以当你的编译器提示不支持的语法时,请检查你是否开启了 C99 选项或更高的版本支持。

C99 标准的定义如下:

struct test {
    short len;  // 必须至少有一个其它成员
    char arr[]; // 柔性数组必须是结构体最后一个成员(也可是其它类型,如:int、double、...)
};
 

在一个结构体的最后,申明一个长度为空的数组,就可以使得这个结构体是可变长的。对于编译器来说,此时长度为 0 的数组并不占用空间,因为数组名本身不占空间,它只是一个偏移量,数组名这个符号本身代表了一个不可修改的地址常量,

但对于这个数组的大小,我们可以进行动态分配,对于编译器而言,数组名仅仅是一个符号,它不会占用任何空间,它在结构体中,只是代表了一个偏移量,代表一个不可修改的地址常量!

对于柔性数组的这个特点,很容易构造出变成结构体,如缓冲区,数据包等等, 其实柔性数组成员在实现跳跃表时有它特别的用法,在Redis的SDS数据结构中和跳跃表的实现上,也使用柔性数组成员。它的主要用途是为了满足需要变长度的结构体,为了解决使用数组时内存的冗余和数组的越界问题。 

柔性数组解决引言的例子

//柔性数组
struct soft_buffer
{
    int   len;
    char  data[0];
};
 

数据结构大小 = sizeof(struct soft_buffer) = sizeof(int),这样的变长数组常用于网络通信中构造不定长数据包, 不会浪费空间浪费网络流量。

申请内存:

if ((softbuffer = (struct soft_buffer *)malloc(sizeof(struct soft_buffer) + sizeof(char) * CUR_LENGTH)) != NULL)
{
    softbuffer->len = CUR_LENGTH;
    memcpy(softbuffer->data, "softbuffer test", CUR_LENGTH);
    printf("%d, %s\n", softbuffer->len, softbuffer->data);
}
 

释放内存:

free(softbuffer);
softbuffer = NULL;

对比使用指针和柔性数组会发现,使用柔性数组的优点:

缺点:对结构体格式有要求,必要放在最后,不是唯一成员。

到此,关于“c++柔性数组是什么”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

推荐阅读:
  1. 柔性数组
  2. C++之Asio库是什么

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

c++

上一篇:JavaScript如何使用!!操作符转换布尔值

下一篇:JavaScript如何使用+将字符串转换成数字

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》