Redis(一)之 struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)))讲解
看Redis的源码的时候,我有点好奇,不知道
struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)))
是啥意思,所以就了解了下,首先我们看sdshdr的结构体
/*
* 类型别名,用于指向 sdshdr 的 buf 属性
*/
typedef char *sds;
/*
* 保存字符串对象的结构
*/
struct sdshdr {
// buf 中已占用空间的长度
int len;
// buf 中剩余可用空间的长度
int free;
// 数据空间
char buf[];
};
首先我们得知道
char buf[]
这个数组没有大小,是所谓的柔性数组,是不占据内存大小的,所以sizeof(struct sdshdr)
为8。
还有sds数据类型为char*类型,从定义可以看出,然后我们再来看这个结构体的初始化
sds sdsnewlen(const void *init, size_t initlen) {
struct sdshdr *sh;
// 根据是否有初始化内容,选择适当的内存分配方式
// T = O(N)
if (init) {
// zmalloc 不初始化所分配的内存
sh = zmalloc(sizeof(struct sdshdr)+initlen+1);
} else {
// zcalloc 将分配的内存全部初始化为 0
sh = zcalloc(sizeof(struct sdshdr)+initlen+1);
}
// 内存分配失败,返回
if (sh == NULL) return NULL;
// 设置初始化长度
sh->len = initlen;
// 新 sds 不预留任何空间
sh->free = 0;
// 如果有指定初始化内容,将它们复制到 sdshdr 的 buf 中
// T = O(N)
if (initlen && init)
memcpy(sh->buf, init, initlen);
// 以 \0 结尾
sh->buf[initlen] = '\0';
// 返回 buf 部分,而不是整个 sdshdr
return (char*)sh->buf;
}
我们这里可以看到len和free还有buf的在内存中是一块的,然后我们的sds是指到字符串buf的位置的,所以
struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)))
就指到了结构体的头部,如图所示。
基本就是这样。