iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >柔性数组(Redis源码学习)
  • 261
分享到

柔性数组(Redis源码学习)

柔性数组(Redis源码学习) 2019-06-16 02:06:46 261人浏览 绘本
摘要

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

柔性数组(Redis源码学习)

柔性数组(Redis源码学习)

1. 问题背景

在阅读Redis源码中的字符串有如下结构,在sizeof(struct sdshdr)得到结果为8,在后续内存申请和计算中也用到。其实在工作中有遇到过这种 struct结构 + 应用数据的情况,但没有意识到自己使用的是柔性数组,在学习阅读Redis代码中,遇到该方法,就特总结记录之。


typedef char * sds;

struct sdshdr {    
    // buf 中已占用空间的长度
    int len;
    // buf 中剩余可用空间的长度
    int free;
    // 数据空间
    char buf[];
};

2. 柔性数组

柔性数组(flexible array member)也叫伸缩性数组成员,这种结构产生与对动态结构体的去求。在日常编程中,有时需要在结构体中存放一个长度是动态的字符串(也可能是其他数据类型)。

一般的做法,是在结构体中定义一个指针成员,这个指针成员指向该字符串所在的动态内存空间。在通常情况下,如果想要高效的利用内存,那么在结构体内部定义静态的数组是非常浪费的行为。其实柔性数组的想法和动态数组的想法是一样的。

柔性数组用来在结构体中存放一个长度动态的字符串。
本文基于redis 的sds.c源码,进行简单编码验证测试,其实这种柔性数组,在工作中用到过,但是没有意识到这是柔性数组。

上述struct sdshdr结构中,要注意:最后一个变量 buf 数组中,没有长度,这和自己遇到的正常的使用方式不一样,新的知识点
这种用法是C语言中的柔性数组,上面 的sizeof(sdshdr )结果是8,即后面的buf不占空间,只是一个符号,测试上面sdshdr结果如下:

int main(int arGC,char **argv){	   
	struct sdshdr t;	  
    
    printf("int len:%d
",sizeof(int));	
	printf("sdshdr len:%d
",sizeof(struct sdshdr));
	  
    printf("Address:
");
    printf("t	 %p
", &t);
    printf("t.len	 %p
", &(t.len));
    printf("t.free	 %p
", &(t.free));	
    printf("t.buf	 %p
", &(t.buf));	
	return 0;	
}

RHEL6.9上执行上面代码块得到结果如下:

$ ./sdshdr                  
int len:4
sdshdr len:8
Address:
t        0x7fff9572fa50
t.len    0x7fff9572fa50
t.free   0x7fff9572fa54
t.buf    0x7fff9572fa58

可以看到 t.buf 是该结构的最后的地址,是最后一个点,简单图示如下:

image

如果后续再malloc相关的内存,则就会在t.buf后面连续,简单编写代码进行验证。要加入对应的sds.h文件,或者直接将结构定义在main函数之前。

int main(int argc,char **argv){	   
	struct sdshdr t;	  
	  
	printf("int len:%d
",sizeof(int));	
	printf("sdshdr len:%d
",sizeof(struct sdshdr));
	  
    printf("Address:
");
    printf("t	 %p
", &t);
    printf("t.len	 %p
", &(t.len));
    printf("t.free	 %p
", &(t.free));	
    printf("t.buf	 %p
", &(t.buf));	
    
    printf("sizeof(char):	 %d
", sizeof(char));	
    struct sdshdr *p=(struct sdshdr*)malloc(sizeof(struct sdshdr) + sizeof(char)*8);
    printf("After malloc the struct"s size is %d
",sizeof(struct sdshdr));

    printf("Address:
");
    printf("p	 %p
", p);
    printf("p->len	 %p
", &(p->len));
    printf("p->free	 %p
", &(p->free));	
    printf("p->buf	 %p,sizeof(p):%d
", &(p->buf),sizeof(p));	
    
    memset(p,0,sizeof(struct sdshdr) + sizeof(char)*8);
    char *str="Hello";
    memcpy(p->buf,str,strlen(str));
    printf("p->buf:%s
",p->buf);
    
    char *str1="HelloWorldttttttt";
    memcpy(p->buf,str1,sizeof(char)*8-1);
    printf("p->buf:%s
",p->buf);
    printf("strlen(p->buf):%d
",strlen(p->buf));
	  return 0;	
}

上述代码进行编译,获得可执行文件,执行结果如下:

$ ./sdshdr                  
int len:4
sdshdr len:8
Address:
t        0x7ffea0a8c420
t.len    0x7ffea0a8c420
t.free   0x7ffea0a8c424
t.buf    0x7ffea0a8c428
sizeof(char):    1
After malloc the struct"s size is 8
Address:
p        0x1bc3010
p->len   0x1bc3010
p->free  0x1bc3014
p->buf   0x1bc3018,sizeof(p):8
p->buf:Hello
p->buf:HelloWo
strlen(p->buf):7
$


## 3. 使用方法
从C99开始便支持了不完整类型实现柔性数组成员。为什么使用不完整类型呢?
```C language
int a[] = {10};

看到这个声明语句,我们发现a[]其实就是个数组记号,不完整类型,由于赋值语句,所以在编译时便确定了数组的大小,是一个完整的数组类型。
在结构体中便利用不完整类型在运行对动态的数组进行指明。
C99标准的定义如下:

struct Test{
    int a;
    char p[]; // 不只是char类型,其他类型同样也是可以
}

由于声明内存连续性的关系,柔性数组成员必须定义在结构体的最后一个,并且不能是唯一的成员。
我们再来看一看整个结构体(包含数组内存的分布情况),进行简单编码验证。

#include 
#include 
#include 
typedef struct Test
{
    int a;
    char p[];
} Test;
int main()
{
    Test *t=(Test*)malloc(sizeof(Test)+sizeof(char)*(10+1));
    printf("sizeof(int):%d,sizeof(Test):%d
",sizeof(int),sizeof(Test));
    strcpy(t->p,"hello");
    printf("t->p:%s
", (t->p));
    printf("Address:
");
    printf("t	 %p
", t);
    printf("t.a	 %p
", &(t->a));
    printf("t.p	 %p
", (t->p));    
    free(t);    //只需要释放一次内存
    return 0;
}

linux上的执行结果如下:

$ ./sdshdr                  
sizeof(int):4,sizeof(Test):4
t->p:hello
Address:
t        0x7e0010
t.a      0x7e0010
t.p      0x7e0014

4. 小结

  1. 在结构体中存放一个长度是动态数据类型时,可以考虑到柔性数组。
  2. 一般做法,是在结构体中定义一个指针成员,这个指针成员指向所在的动态内存空间。
  3. 该指针成员,不占结构体空间,只是一个符号。
  4. 柔性数组成员必须定义在结构体的最后一个,并且不能是唯一的成员。

5. 参考文献

https://www.cnblogs.com/davygeek/p/5748852.html

Https://blog.csdn.net/qq_40477151/article/details/78905567

https://www.cnblogs.com/pluviophile/p/7571410.html

本人才疏学浅,参考网络文章及代码验证,如有错误不当之处,请批评指正,如有侵权,请立即联系我进行删除。

如果能为您带来一点点帮助,那将是我的荣幸,多谢您关注和转发推荐,谢谢!

image

您可能感兴趣的文档:

--结束END--

本文标题: 柔性数组(Redis源码学习)

本文链接: https://www.lsjlt.com/news/8555.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C语言柔性数组详解
    目录前言一、柔性数组是什么?二、柔性数组的特点三、柔性数组的优点总结前言 可能大家第一眼看到这个标题会有点懵,到底什么是柔性数组,我怎么从来没听说过?但柔性数组确实是存在的,也经常会...
    99+
    2024-04-02
  • 详解C语言之柔性数组
    目录定义特点具体使用例总结定义 可调整大小的数组 以0大小数组或无大小数组定义在结构体的最后一个元素中 特点 1.结构体中的柔性数组前必须包含至少一个其他成员。 2.sizeof...
    99+
    2024-04-02
  • C语言中柔性数组怎么用
    这篇文章主要为大家展示了“C语言中柔性数组怎么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“C语言中柔性数组怎么用”这篇文章吧。定义可调整大小的数组以0大小数组或无大小数组定义在结构体的最后一...
    99+
    2023-06-25
  • C语言如何使用柔性数组
    这篇文章主要介绍了C语言如何使用柔性数组,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一.柔性数组的特点struct S{int x;int a...
    99+
    2023-06-29
  • C语言柔性数组怎么使用
    今天小编给大家分享一下C语言柔性数组怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一、前言仔细观察下面的代码,有没有...
    99+
    2023-07-05
  • Vue源码学习之数据初始化
    目录初始化数据创建Vue实例构造函数扩展方法初始化状态调用initData方法对数据进行代理初始化数据 环境搭建:菜鸟学Vue源码第一步之rollup环境搭建步 响应式数据的核心就是...
    99+
    2024-04-02
  • C语言中0数组\柔性数组的使用详解
    前言: 上次看到一篇面试分享,里面有个朋友说,面试官问了char[0] 相关问题,但是自己没有遇到过,就绕过了这个问题。 我自己在这篇文章下面做了一些回复。 现在我想结合我自己...
    99+
    2024-04-02
  • C语言 柔性数组的使用详解
    目录一.柔性数组的特点二.柔性数组的使用1.如何使用柔性数组2.不用柔性数组的话有什么代替三.柔性数组的优势1.方便内存释放2.提高访问速度一.柔性数组的特点 struct S {...
    99+
    2024-04-02
  • C语言中的柔性数组怎么使用
    这篇文章主要讲解了“C语言中的柔性数组怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C语言中的柔性数组怎么使用”吧!1.什么是柔性数组柔性数组就是大小可以变化的数组。注意跟C99中的...
    99+
    2023-07-06
  • elementui源码学习之仿写一个el-divider组件
    目录正文组件需求分析组件中用到的知识点函数式组件函数式组件的两种定义方式解决一像素太粗的问题组件封装组件封装的效果图组件封装的代码正文 本篇文章记录仿写一个el-divider组件细...
    99+
    2022-11-13
    elementui仿写el-divider elementui el-divider
  • C语言中的柔性数组你了解吗
    目录1.什么是柔性数组2.柔性数组应该如何使用3.柔性数组的替代方案及内存分布对比4.柔性数组有哪些优点总结1.什么是柔性数组 柔性数组就是大小可以变化的数组。 注意跟C99中的变长...
    99+
    2023-05-15
    C语言柔性数组使用 C语言 柔性数组 C语言 数组
  • 关于slf4j_log4j2源码学习心得
    目录日志工厂获取Logger日志输出Logger.info异步日志写入异步日志上下文选择locateContext定位选择日志上下文总结日志工厂获取Logger 获取日志工厂_ge...
    99+
    2024-04-02
  • Python源码学习之PyObject和PyTypeObject
    前言 Python是C语言实现的,因此Python对象在C语言层面应该是一个结构体 ,组织对象占用的内存。 不同类型的对象,数据及行为均可能不同,因此可以大胆猜测:不同类型的对象由不...
    99+
    2024-04-02
  • Python 数组 path 学习笔记:如何优化数组性能?
    Python 中的数组是一种非常常见的数据结构,它可以用来存储一系列的元素,并且支持随机访问和修改。在实际编程中,我们经常需要对数组进行一些操作,如查找、插入、删除等,而这些操作的效率往往会对程序的性能产生很大的影响。因此,如何优化数组性...
    99+
    2023-08-19
    数组 path 学习笔记
  • 深入了解一下C语言中的柔性数组
    目录什么是柔性数组柔性数组的使用什么是柔性数组 柔性数组是在C99中定义的 结构体的最后一个元素允许是未知大小的数组,这就叫柔性数组 柔性数组的长度可以写成0,也可以不规定数组长度 ...
    99+
    2023-02-13
    C语言柔性数组使用 C语言柔性数组
  • Python内建类型int源码学习
    目录1 int对象的设计1.1 PyLongObject1.2 整数的布局1.3 小整数静态对象池1.4 示例2 大整数运算2.1 整数运算概述2.2 大整数运算处理过程1.long...
    99+
    2024-04-02
  • 通过JDK源码学习InputStream详解
    概况本文主要给大家介绍了通过JDK源码学习InputStream的相关内容,JDK 给我们提供了很多实用的输入流 xxxInputStream,而 InputStream 是所有字节输入流的抽象。包括 ByteArrayInputStrea...
    99+
    2023-05-30
    inputstream jdk源码 npu
  • Python内建类型str源码学习
    目录引言1 Unicode2 Python中的Unicode2.1 Unicode对象的好处2.2 Python对Unicode的优化3 Unicode对象的底层结构体3.1 PyA...
    99+
    2024-04-02
  • C语言中的柔性数组你真的了解吗
    目录柔性数组概念:特点:与指针动态开辟的比较指针动态开辟柔性数组指针动态开辟的缺点总结柔性数组概念: 柔性数组就是一种特殊的数组 它也是结构体最后一个成员 也就是说,它存在结构体最后...
    99+
    2024-04-02
  • flume源码学习3-自动reload配
      在1.5.0的flume版本中开始提供这个功能,判断配置文件的更新时间戳来reload服务原理:1)在启动中使用EventBus.register注册Application对象,同时Application有一个Subscribe的方法h...
    99+
    2023-01-31
    源码 flume reload
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作