• Redis中String字符串sdshdr结构体的讲解


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

    1. struct sdshdr {
    2. int len;
    3. int free;
    4. char buf[];
    5. };

    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讲解

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

    首先需要明白:

    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讲解

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

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

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

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

    总结:

    最后,如果本帖对您有一定的帮助,希望能点赞+关注+收藏!您的支持是给我最大的动力,后续会一直更新各种框架的使用和框架的源码解读~!

  • 相关阅读:
    [附源码]计算机毕业设计JAVAjsp建筑公司门户网站
    Java基础——反射
    自控力第一章
    oracle_申明与赋值
    记录了解php8-JIT
    信息系统项目管理师必背核心考点(五十三)质量等级
    Avalonia常用小控件Menu
    Stream方法的介绍
    全面理解元宇宙-Web3.0具象表现形式
    STL中list实现
  • 原文地址:https://blog.csdn.net/qq_43799161/article/details/126306177