Redis中String字符串和sdshdr结构体超详细讲解

 更新时间:2023年04月10日 10:13:52   作者:程序员李哈  
这篇文章主要介绍了Redis中String字符串和sdshdr结构体,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧

前言

在redis中对字符串的处理,个人觉得特别的优雅,所以特意写这篇帖子来分享一下对其的理解。

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

len是长度

free是目前空闲的长度

buf是实际存储的字符数组

很多读者,第一次见到char buf[],会感到到,这不是数组么,怎么还能不传入初始大小???

为了用官方的论证这个char buf[],笔者特意找到GCC手册中6.17 Arrays of Length Zero章节,以下截图是对其的描述。

GCC手册的论证

一言以蔽之:就是GCC编译器在ISO C99的C语言规范中支持动态数组。并且初始长度为0。并且只能出现在结构体中最后一个成员。

既然redis定义了自己的字符串形式,那么对字符串的操作那比不可少,所以下面挑选几个api对其讲解。实际上,细心的读者可以发现,其实每个api的操作大同小异,都是通过指针的骚操作得到sdshdr结构体,然后取值。

sdslen讲解

static inline size_t sdslen(const sds s) {
    struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
    return sh->len;
}

首先需要明白:

sizeof(struct sdshdr) = 8

因为由GCC文档得知可变数组在初始化的过程中大小为0,所以sizeof(struct sdshdr) 仅仅是2个int的大小2*4 = 8;

其次方法参数const sds s是传入的char*地址。也就是sdshdr结构体中char buf[];的地址。

所以使用char buf[];的地址 - 8 就是sdshdr结构体的地址。

文字描述可能存在理解偏差,所以笔者借用图形化来方便读者的理解,如下图所示。

sdsnewlen讲解

// void *init是初始化的字符串
// size_t initlen是长度
sds sdsnewlen(const void *init, size_t initlen) {
    struct sdshdr *sh;
    if (init) {
        // 因为sizeof(struct sdshdr)长度不计算char buf[],
        // 所以开辟大小需要加上initlen,为什么要+1,因为字符串'\0'结尾,所以要+1的大小。
        sh = zmalloc(sizeof(struct sdshdr)+initlen+1);
    } else {
        sh = zcalloc(sizeof(struct sdshdr)+initlen+1);
    }
    if (sh == NULL) return NULL;
    sh->len = initlen;
    sh->free = 0;
    // 把传入的字符串拷贝到sdshdr结构体中的char buf[]中。
    if (initlen && init)
        memcpy(sh->buf, init, initlen);
    // 把字符串的最后一位赋值为'\0'
    sh->buf[initlen] = '\0';
    // 返回char buf[]的地址
    return (char*)sh->buf;
}

仔细的讲解都在代码的注释中。

这里需要注意一点,就是sizeof(struct sdshdr)长度不计算char buf[],所以开辟大小需要加上initlen,为什么要+1,因为字符串'\0'结尾,所以要+1的大小。

其他的api大同小异,就不一一的做讲解了。

总结

到此这篇关于Redis中String字符串和sdshdr结构体超详细讲解的文章就介绍到这了,更多相关Redis String字符串内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java 将list集合数据按照时间字段排序的方法

    Java 将list集合数据按照时间字段排序的方法

    这篇文章主要介绍了Java 将list集合数据按照时间字段排序,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-03-03
  • Java泛型和Class类用法示例

    Java泛型和Class类用法示例

    这篇文章主要介绍了Java泛型和Class类用法,结合实例形式分析了java使用泛型限制class类避免强制类型转换相关操作技巧,需要的朋友可以参考下
    2019-07-07
  • 浅谈Spring-cloud 之 sleuth 服务链路跟踪

    浅谈Spring-cloud 之 sleuth 服务链路跟踪

    本篇文章主要介绍了浅谈Spring-cloud 之 sleuth 服务链路跟踪,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01
  • JDBC编程实现文件、图片的存储方法

    JDBC编程实现文件、图片的存储方法

    这篇文章主要介绍了JDBC编程实现文件、图片的存储方法,以实例形式分析了Java基于JDBC操作数据库的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-10-10
  • mybatis-plus版本不兼容问题的解决

    mybatis-plus版本不兼容问题的解决

    本文主要介绍了mybatis-plus与spring-boot3版本不兼容导致的BeanDefinitionStoreException问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-12-12
  • idea中的jvm调优方式

    idea中的jvm调优方式

    这篇文章主要介绍了idea中的jvm调优方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • SpringBoot接值实现方法详解

    SpringBoot接值实现方法详解

    这篇文章主要介绍了SpringBoot接值实现方法,SpringBoot接值是指在SpringBoot应用程序中接收请求参数,从HTTP请求中获取参数,并将其绑定到Java对象中进行处理的过程,感兴趣想要详细了解可以参考下文
    2023-05-05
  • 详解Java中的反射机制和动态代理

    详解Java中的反射机制和动态代理

    本文将详细介绍反射机制以及动态代理机制,而且基本现在的主流框架都应用了反射机制,如spring、MyBatis、Hibernate等等,这就有非常重要的学习意义
    2021-06-06
  • java异步执行代码处理方法(先返回结果,后执行代码)

    java异步执行代码处理方法(先返回结果,后执行代码)

    这篇文章主要给大家介绍了关于java异步执行代码处理方法的相关资料,先返回结果,后执行代码,文中通过实例代码介绍的非常详细,对大家的学习或者工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-07-07
  • java实现Dijkstra最短路径算法

    java实现Dijkstra最短路径算法

    这篇文章主要为大家详细介绍了java实现Dijkstra最短路径算法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-01-01

最新评论