Sds (Simple Dynamic String,简单动态字符串)是 Redis 底层所使用的字符串表示,
Sds 在 Redis 中的主要作用有以下两个:
- 实现字符串对象(StringObject);
- 在 Redis 程序内部用作 char* 类型的替代品;
typedef char *sds;
struct sdshdr {
// buf 已占用长度
int len;
// buf 剩余可用长度
int free;
// 实际保存字符串数据的地方
char buf[]; //柔性数组成员
};
//字符串的数据结构,记录了字符串长度、空闲字节,以及指向实际存储数据buf的指针,这里sds就是我们常用的char *字符串,sdshdr就相当于字符串的管理结构,如free等
static inline size_t sdslen(const sds s) { //返回字符串的长度
struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
return sh->len;
}
//s是char *类型,sizeof(struct sdshdr)只包含len和free的字节数,所以 s-(sizeof(struct sdshdr) 就是结构体首地址,也即是len 的地址,但如果sdshdr按下面定义
struct sdshdr { // buf 已占用长度 int len; // buf 剩余可用长度 int free; // 实际保存字符串数据的地方 char *buf; };
则包含buf占用的字节数,在64位机下sizeof(struct sdshdr)=16, sizeof(char *)=8 ,请参看柔性数组成员
http://blog.csdn.net/zhongguoren666/article/details/7953831
static inline size_t sdsavail(const sds s) { //返回空闲字节数 struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr))); return sh->free; }
最后简单说下双端链表
其中, listNode 是双端链表的节点: typedef struct listNode { // 前驱节点 struct listNode *prev; // 后继节点 struct listNode *next; // 值 void *value; } listNode; 而 list 则是双端链表本身: typedef struct list { // 表头指针 listNode *head; // 表尾指针 listNode *tail; // 节点数量 unsigned long len; // 复制函数 void *(*dup)(void *ptr); // 释放函数 void (*free)(void *ptr); // 比对函数 int (*match)(void *ptr, void *key); } list; 注意, listNode 的 value 属性的类型是 void * ,说明这个双端链表对节点所保存的值的类型不做限制。
注意这里结构体里带函数指针,C++代码结构体相当于class ,可以带函数,C语言的结构体里不可能带函数,但可以保存函数指针,常用作回调函数。