redis 源代码之数据结构(2)--sds实现

1,sds(simple dynamic string)作为redis作者自己实现的字符串类型,是redis的基本数据类型。

typedef char *sds;

struct sdshdr {
    int len;
    int free;
    char buf[];
};

可以看到  sds本质上是一个char指针,内部存储结构为一个header+char*. len表示sds实际占用的空间大小, free表示sds尚未使用的空间。buf指向实际的字符串内容。

sizeof(struct sdshsr)在32位操作系统下面是8,redis作者没有用char *buf,是不是觉得这样一个头部就可以节约4字节内存?char buf[]被gcc编译器理解为动态数组了,而且buf变量只能放在结构体最后位置。否则报错。

2, 关于sds的操作

1)创建sds

sds.c有三个函数用于创建sds

sds sdsnewlen(const void *init, size_t initlen);//主要的创建函数
sds sdsnew(const char *init);//这个函数实际上调用的sdsnewlen,initlen问 字符串init的大小(不包含最后的‘\0’)
sds sdsempty();//同调用sdsnewlen,只不过initlen为0

sdsnewlen的具体代码

sds sdsnewlen(const void *init, size_t initlen) {
    struct sdshdr *sh;

    if (init) {
        sh = zmalloc(sizeof(struct sdshdr)+initlen+1);  //一个sds真正的占用空间为头部大小+字符串长度
    } else {
        sh = zcalloc(sizeof(struct sdshdr)+initlen+1);
    }
    if (sh == NULL) return NULL;
    sh->len = initlen;                           //此处的len,没有把'\0‘计算在内
    sh->free = 0;
    if (initlen && init)
        memcpy(sh->buf, init, initlen);
    sh->buf[initlen] = '\0';
    return (char*)sh->buf;    //返回的指针指向真正字符串内容,而不是返回头部指针,这样用户之需要关心真正的内容就行,不需要管理头部
}
如果这样调用

sds mysds = sdsnewlen("redis", 5);
那么内存结构图为


那么如何获取头部信息呢,比如说我想获取sds的长度(buf长度)

static inline size_t sdslen(const sds s) {
    struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));//往前偏移
    return sh->len;
}
用sds指针向前移动sizeof(struct sdshdr) 字节(就是减去)就可以指向头部了。从而获取sds的头部相关信息。

2)sds释放

void sdsfree(sds s) {
    if (s == NULL) return;
    zfree(s-sizeof(struct sdshdr));
}
利用redis作者封装的free函数释放掉所有的内存,当然包括头部。

3)sds其他操作这里就不再叙述,基本上常见的字符串的操作都可以找到。








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值