柔性数组(Redis源码学习)
柔性数组(Redis源码学习)
1. 问题背景
在阅读Redis源码中的字符串有如下结构,在sizeof(struct sdshdr)
得到结果为8,在后续内存申请和计算中也用到。其实在工作中有遇到过这种 struct结构 + 应用数据的情况,但没有意识到自己使用的是柔性数组,在学习阅读Redis代码中,遇到该方法,就特总结记录之。
/* * 类型别名,用于指向 sdshdr 的 buf 属性 */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\n",sizeof(int)); printf("sdshdr len:%d\n",sizeof(struct sdshdr)); printf("Address:\n"); printf("t\t %p\n", &t); printf("t.len\t %p\n", &(t.len)); printf("t.free\t %p\n", &(t.free)); printf("t.buf\t %p\n", &(t.buf)); return 0; }
RHEL6.9上执行上面代码块得到结果如下:
$ ./sdshdr int len:4sdshdr len:8Address:t 0x7fff9572fa50t.len 0x7fff9572fa50t.free 0x7fff9572fa54t.buf 0x7fff9572fa58
可以看到 t.buf 是该结构的最后的地址,是最后一个点,简单图示如下:
如果后续再malloc相关的内存,则就会在t.buf后面连续,简单编写代码进行验证。要加入对应的sds.h文件,或者直接将结构定义在main函数之前。
int main(int argc,char **argv){ struct sdshdr t; printf("int len:%d\n",sizeof(int)); printf("sdshdr len:%d\n",sizeof(struct sdshdr)); printf("Address:\n"); printf("t\t %p\n", &t); printf("t.len\t %p\n", &(t.len)); printf("t.free\t %p\n", &(t.free)); printf("t.buf\t %p\n", &(t.buf)); printf("sizeof(char):\t %d\n", sizeof(char)); struct sdshdr *p=(struct sdshdr*)malloc(sizeof(struct sdshdr) + sizeof(char)*8); printf("After malloc the struct's size is %d\n",sizeof(struct sdshdr)); printf("Address:\n"); printf("p\t %p\n", p); printf("p->len\t %p\n", &(p->len)); printf("p->free\t %p\n", &(p->free)); printf("p->buf\t %p,sizeof(p):%d\n", &(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\n",p->buf); char *str1="HelloWorldttttttt"; memcpy(p->buf,str1,sizeof(char)*8-1); printf("p->buf:%s\n",p->buf); printf("strlen(p->buf):%d\n",strlen(p->buf)); return 0; }
上述代码进行编译,获得可执行文件,执行结果如下:
$ ./sdshdr int len:4sdshdr len:8Address:t 0x7ffea0a8c420t.len 0x7ffea0a8c420t.free 0x7ffea0a8c424t.buf 0x7ffea0a8c428sizeof(char): 1After malloc the struct's size is 8Address:p 0x1bc3010p->len 0x1bc3010p->free 0x1bc3014p->buf 0x1bc3018,sizeof(p):8p->buf:Hellop->buf:HelloWostrlen(p->buf):7$## 3. 使用方法从C99开始便支持了不完整类型实现柔性数组成员。为什么使用不完整类型呢?```C languageint a[] = {10};
看到这个声明语句,我们发现a[]其实就是个数组记号,不完整类型,由于赋值语句,所以在编译时便确定了数组的大小,是一个完整的数组类型。
在结构体中便利用不完整类型在运行对动态的数组进行指明。
C99标准的定义如下:
struct Test{ int a; char p[]; // 不只是char类型,其他类型同样也是可以}
由于声明内存连续性的关系,柔性数组成员必须定义在结构体的最后一个,并且不能是唯一的成员。
我们再来看一看整个结构体(包含数组内存的分布情况),进行简单编码验证。
#include <stdio.h>#include <stdlib.h>#include <string.h>typedef struct Tes......原文转载:http://www.shaoqun.com/a/839190.html
跨境电商:https://www.ikjzd.com/
Zozo:https://www.ikjzd.com/w/2180
haofang:https://www.ikjzd.com/w/1046
naver:https://www.ikjzd.com/w/1727
柔性数组(Redis源码学习)1.问题背景在阅读Redis源码中的字符串有如下结构,在sizeof(structsdshdr)得到结果为8,在后续内存申请和计算中也用到。其实在工作中有遇到过这种struct结构+应用数据的情况,但没有意识到自己使用的是柔性数组,在学习阅读Redis代码中,遇到该方法,就特总结记录之。/**类型别名,用于指向sdshdr的buf属性*/typedefchar*sds
良心干货:2019新卖家做跨境电商,选哪个平台最赚钱?:https://www.ikjzd.com/articles/106864
出乎意料的福音?亚马逊终于开始为卖家着想了!:https://www.ikjzd.com/articles/106866
特朗普又作妖,美国下月将"退群"万国邮联!:https://www.ikjzd.com/articles/106867
亚马逊Listing优化需要考虑哪些?:https://www.ikjzd.com/articles/106869
躲在瓜棚日儿媳妇。 那天我再也忍不住疯狂把儿媳妇摁在地上:http://lady.shaoqun.com/a/274731.html
口述我同时接两个客人 他们三个弄我一个晚上:http://lady.shaoqun.com/m/a/248083.html
囗述我互换丈夫过程 邻居大棒在我体内不停抽搐:http://lady.shaoqun.com/m/a/246753.html
交换第一次,我的第一次换妻真实感受:http://www.30bags.com/m/a/249690.html
婚后如何保持夫妻性生活和谐的秘诀:http://lady.shaoqun.com/a/394629.html
有钱就可以泡妞?那是因为我没遇到诡计多端的婊子!:http://lady.shaoqun.com/a/394630.html
《灭火轮》中50岁男子"性压抑"的故事,揭示了老人无法言说的痛苦:http://lady.shaoqun.com/a/394631.html
一个男人有多强大才能让她一次次高潮:http://lady.shaoqun.com/a/394632.html
Comments
Post a Comment