redis 沒有直接使用 c 語言傳統的字串表示(以空字元結尾的字元陣列,以下簡稱 c 字串), 而是自己構建了一種名為簡單動態字串(****** dynamic string,sds)的抽象型別, 並將sds用作 redis 的預設字串表示。
sds簡單動態字串資料結構如下:
1 typedef char *sds;23len記錄字串的長度,free記錄sds還剩餘的空間,buf指向儲存字元的空間。struct
sdshdr ;
對應的記憶體空間如下圖:
例如最開始要存放字串「chenrancc」:
一般開始的時候會比初始字串多申請乙個長度的空間放\0,如上圖所示,對應的函式是sdsnewlen。
刪除後面的cc字元後:
刪除後面的cc字元後,空出兩個字元空間並不會**,而是用free來記錄。如果要**者兩個空閒的空間,必須重新分配乙個新的sds,做法是將原來的sds通過realloc重新分配成新的sds,對應的函式為sdsremovefreespace。如果要增加sds的空間,也是用同樣的方法通過realloc重新分配乙個新的sds,對應的函式是sdsmakeroomfor。
要**sds所在的記憶體空間,可以通過函式sdsfree,它實際呼叫的是free函式。
除了上面提到的函式,sds中還定義了很多其它的函式來方便上層使用:
1 sds sdsnewlen(constview codevoid *init, size_t initlen); //
用長度為initlen的字串建立sds
2 sds sdsempty(void); //
建立乙個長度為0的sds
3 sds sdsnew(const
char *init); //
用null結尾的字串建立sds
4 sds sdsdup(const sds s); //
拷貝乙個sds
5void sdsfree(sds s); //
釋放sds所佔的記憶體空間
6void sdsupdatelen(sds s); //
更新sds中的len為實際的字串長度
7void sdsclear(sds s); //
將sds中的字串為空串
8 sds sdsmakeroomfor(sds s, size_t addlen); //
sds字串所佔空間增加addlen個字元(包括free所佔的字元)
9 sds sdsremovefreespace(sds s); //
去除sds中空閒的空間
10 size_t sdsallocsize(sds s); //
獲取sds實際占用空間的大小
11void sdsincrlen(sds s, int incr); //
sds實際字串的長度增加incr
12 sds sdsgrowzero(sds s, size_t len); //
將sds所佔的空間增加到len,增加的空間都清零
13 sds sdscatlen(sds s, const
void *t, size_t len); //
sds末尾連線乙個長度為len的字串
14 sds sdscat(sds s, const
char *t); //
sds末尾連線乙個以null結尾的字串
15 sds sdscatsds(sds s, const sds t); //
sds末尾連線另乙個sds
16 sds sdscpylen(sds s, const
char *t, size_t len); //
拷貝長度為len的字串到sds中
17 sds sdscpy(sds s, const
char *t); //
拷貝以null結尾的字串到sds中
18 sds sdscatvprintf(sds s, const
char *fmt, va_list ap); //
sds末尾連線乙個由可變引數形成的字串
19 sds sdscatprintf(sds s, const
char *fmt, ...); //
sds末尾連線乙個由可變引數形成的字串
20 sds sdstrim(sds s, const
char *cset); //
去除sds字串的前後字元,這些字元都是在cset中出現過的
21void sdsrange(sds s, int start, int end); //
獲取sds字串的乙個字串,start和end可以為負數,負數表示從後面往前面索引
22void sdstolower(sds s); //
將sds字串中的字元設定為小寫
23void sdstoupper(sds s); //
將sds字串中的字元設定為大寫
24int sdscmp(const sds s1, const sds s2); //
比較兩個字串的大小
25 sds *sdssplitlen(const
char *s, int len, const
char *sep, int seplen, int *count); //
用字串sdp分割乙個sds為多個sds
26void sdsfreesplitres(sds *tokens, int count); //
釋放由函式sdssplitlen返回的sds陣列空間
27 sds sdsfromlonglong(long
long value); //
將long long型別的數字轉化為乙個sds
28 sds sdscatrepr(sds s, const
char *p, size_t len); //
sds末尾連線乙個長度為len的字串,並且將其中的不可列印字元顯示出來
29int is_hex_digit(char c); //
判斷乙個字元釋放為16進製制數字
30int hex_digit_to_int(char c); //
將乙個16進製制數字轉化為整數
31 sds *sdssplitargs(const
char *line, int *argc); //
將一行文字分割成多個引數,每個引數可以用類程式語言 repl格式,如果空格,\n\r\t\0等作為分隔符
32 sds sdsmapchars(sds s, const
char *from, const
char *to, size_t setlen) //
將sds中出現在from中的字元替換為to對應的字元
33 sds sdsjoin(char **argv, int argc, char *sep); //
將多個字串用分割符連線起來組成乙個sds
sds和c++中的vector很類似,唯一不同的是vector在空間不夠的時候可以自動增加2倍的空間。
了解了sds的實現,想想為什麼redis非要自己實現乙個字串,而不是使用c所支援的字串和相關的操作呢?
相比c語言中的字串,sds有如下的好處:
Redis 簡單動態字串
在c語言中,乙個結構體中最後乙個成員的位址減去第乙個成員的位址,就是該結構體的大小 例如 struct sdshdr buf的位址減去len的位址,正好等於sizeof sdshdr 在c 中 char str nihao 是不被允許的,但是c語言中可以,並且可以直接列印str 輸出nihao,和c...
redis簡單動態字串
redis內部使用sds,簡單動態字串,sds是什麼 dynamic t包含字串長度,空間使用率,已使用,未使用等資訊的乙個結構體 sds比c語言字串的優點 獲取字串長度不需要進行遍歷,時間複雜度為o 1 杜絕緩衝區溢位 對sds進行修改的時候,api會先檢查sds的空間是否足夠,如果不需要的話,a...
redis 簡單動態字串
redis沒有直接使用c語言傳統的字串表示,而是自己構建了一種名為簡單動態字串 sds 的抽象型別,並將其作為redis的預設字串表示,即redis中包含字串值的鍵值對在底層都是由sds實現的。每個sds.h sdshdr結構表示乙個sds的值,如下所示 sds遵循c字串以空字元結尾的管理,儲存空字...