sds是redis中用来处理字符串的数据结构。sds的定义在sds.h中:
1 typedef char *sds;
简洁明了!简明扼要!(X,玩我呢是吧!这特么不就是c中的字符串么?!)。像redis这种高端大气上档次的服务器显然不会这么的幼稚。在sds的定义之后,还有一个结构体:
1 struct sdshdr { 2 int len; 3 int free; 4 char buf[]; 5 }
有len,有free,这就有点意思了。很明显,根据这个结构体的定义,这是sds的header,用来存储sds的信息。注意最后的buf定义,这个buf数组没有设置长度。这是为神马呢?在gcc中,这种方式可以使得buf成为一个可变的数组,也就是说,可以扩展buf同时又保证在使用的时候,感觉buf始终在struct sdshdr中。有点啰嗦,其实可以用下图展示:
sdshdr sds | | V V ---------------------------- |len | free | buf … | ----------------------------
这个就是sds的内存分布图。struct sdshdr这个结构体放在了真正的数据之前,且是紧挨着的。这样,通过buf引用的数组其实就是后面的数据。这个是利用了c中数组访问的特点。
下面我们来看看如何创建一个sds:
1 /* Create a new sds string with the content specified by the 'init' pointer 2 * and 'initlen'. 3 * If NULL is used for 'init' the string is initialized with zero bytes. 4 * 5 * The string is always null-termined (all the sds strings are, always) so 6 * even if you create an sds string with: 7 * 8 * mystring = sdsnewlen("abc",3"); 9 * 10 * You can print the string with printf() as there is an implicit at the 11 * end of the string. However the string is binary safe and can contain 12 * characters in the middle, as the length is stored in the sds header. */ 13 sds sdsnewlen(const void *init, size_t initlen) { 14 struct sdshdr *sh; 15 16 if (init) { 17 sh = zmalloc(sizeof(struct sdshdr)+initlen+1); 18 } else { 19 sh = zcalloc(sizeof(struct sdshdr)+initlen+1); 20 } 21 if (sh == NULL) return NULL; 22 sh->len = initlen; 23 sh->free = 0; 24 if (initlen && init) 25 memcpy(sh->buf, init, initlen); 26 sh->buf[initlen] = '