日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Redis中String字符串sdshdr結構體的講解

作者:程序員李哈 更新時間: 2022-08-13 編程語言

?在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大同小異,就不一一的做講解了。

總結:

最后,如果本帖對您有一定的幫助,希望能點贊+關注+收藏!您的支持是給我最大的動力,后續會一直更新各種框架的使用和框架的源碼解讀~!

原文鏈接:https://blog.csdn.net/qq_43799161/article/details/126306177

欄目分類
最近更新