美文网首页C
C 迷你系列(二)柔性数组

C 迷你系列(二)柔性数组

作者: Tubetrue01 | 来源:发表于2021-02-08 18:22 被阅读0次

引言

当我们阅读 Redis 源码的时候,发现有些结构体会有如下一个数组元素:

struct sdshdr5 {
    unsigned char flags; 
    char buf[];
};

思考一下的话,你会发现,我们在声明数组的时候如果不指定大小就需要声明的时候就得初始化,否则就会编译告警。但是恰恰上图所示的数组确可以编译通过。行吧,那么接下来要怎么赋值呢?
假如我们定义如下结构体:

struct People{
    char *username;
    int age;
    char hobbies[];
};
  • 法一 直接赋值
struct People{
    char *username;
    char hobbies[];
} P = {
        "jack",
        {
            "PlayGames"
        }
};
  • 法二 变量赋值
int main()
{
    struct People p = {
            "jack",
            {
                "playGames"
            }
    };
    return 0;
}

方法二编译会报错 Initialization of flexible array member is not allowed ,也就是说是不运行这样赋值的。那么也就是说只能按照法一来赋值了吗?但是看 Redis 时并没有采用上述的方式,那么到底要如何使用呢?

柔性数组

以上数组就是柔性数组,什么是柔性数组呢?我这里就不搬那些标准定义之类的了,用最简单的话说就是不指定长度的数组,而且该数组只能作为结构体的最后一个成员且该成员不能是结构体的唯一成员。

好处

  • 它可以按需分配内存
  • 不占内存空间
  • 内存连续
  • 防止内存碎片

示例

int main()
{
    // 我们声明一个指针变量
    struct People *p;
    // 打印其大小
    printf("size of p is %lu\n", sizeof *p);
    // 为结构体中的数组分配 10 字节大小的空间
    p = (struct People *) malloc(sizeof(struct People) + 10 * sizeof(char));
    // 打印内存
    printf("size of p is %lu\n", sizeof *p);
    char *hobby = "PlayGame";
    // 为数组填充元素
    strncpy(p->hobbies, hobby, strlen(hobby));
    // 再次打印结构大小
    printf("size of p is %lu\n", sizeof *p);
    // 查看元素是否填充
    printf("%s\n", p->hobbies);

    return 0;
}

大家可以思考一下输出。。。

size of p is 8
size of p is 8
size of p is 8
PlayGame

我们发现,p 指向的结构体内存始终是 8 字节,而这个 8 字节就是 username 指针占用的内存大小,也就是说柔性数组不占内存,即使为它分配好内存。

对比指针

将 hobbies 换成指针不照样也可以嘛,如:

struct People
{
    char *username;
    char *hobbies;
};

确实,但是相比柔性数组,指针的方式最大的弊端就是内存释放。也就是说,在释放结构体指针之前要先释放 hobbies 指针,否则就会引起内存泄露。除此之外,由于指针的方式声明的内存与结构体内存并不连续,一方面会造成内存碎片,一方面在访问结构体成员时也不十分便捷,所以才会有柔性数组的出现。

相关文章

  • C 迷你系列(二)柔性数组

    引言 当我们阅读 Redis 源码的时候,发现有些结构体会有如下一个数组元素: 思考一下的话,你会发现,我们在声明...

  • C++中的柔性数组

    描述 C99标准提供在结构体最后一个元素定义一个未知大小的数组,它就叫做柔性数组成员。 柔性数组的特点 定义柔性数...

  • C 实现链表的高速公路-跳跃表

    本文所需基础: 1.知道如何用c写链表。 2.下文将会教到的柔性数组。 预准备(柔性数组): 为了下文讲述方便,先...

  • 零长度数组与柔性数组

    零长度数组(Zero-length array)与柔性数组(Flexible array) GNU C允许使用零长...

  • C柔性数组和变长数组

    变长数组 C语言在C99以前,数组的维度必须是整数常量表达式, 而C99则做了很大改进,允许数组维度为整形变量或者...

  • C 语言之柔性数组

    一 历史 在c99标准出来之前。如果要在某个结构体中使用字符串变时,为了使字符串变量存储地址能与结构体整体连在一起...

  • C语言中的柔性数组

    C语言中 结构体末尾如果是定义的数组,那么这个数组只是一个标识符 并不占用结构体大小。 我们可以在结构体中定义一个...

  • 柔性数组

    在接触变长结构体之前,以为会是一个很难理解的东西,但是这其实算是C里面的一种技巧吧,优点是:分配了一段连续的内存,...

  • Search Insert Position

    标签: C++ 算法 LeetCode 数组 二分查找 每日算法——leetcode系列 问题 SeSearch...

  • Search for a Range

    标签: C++ 算法 LeetCode 数组 二分查找 每日算法——leetcode系列 问题 Search f...

网友评论

    本文标题:C 迷你系列(二)柔性数组

    本文链接:https://www.haomeiwen.com/subject/ylrfxltx.html