在redis中读取sds的源代码时,
typedef char *sds;
struct sdshdr {
unsigned int len;
unsigned int free;
char buf[];
};
static inline size_t sdslen(const sds s) {
struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
return sh->len;
}
我发现,在函数sdslen()中,
struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
为什么不使用“offsetof”而不是“sizeof”,就像这样
struct sdshdr *sh = (void*)(s-(offsetof(struct sdshdr,buf)));
“sizeof”在这里正常工作。但是当结构稍微改变时,代码就会出错。
struct sdshdr {
unsigned int free;
unsigned int len;
char c;
char buf[];
};
int main() {
unsigned int i = offsetof(struct sdshdr, buf);
unsigned int s = sizeof(struct sdshdr);
printf("offset: %u, size: %u\n", i, s);
struct sdshdr *ptr = malloc(sizeof(struct sdshdr) + 100);
printf("sdshdr address: %p\n", ptr);
printf("buf address: %p\n", ptr->buf);
printf("calculate using sizeof: %p\n", ptr->buf - sizeof(struct sdshdr));
printf("calculate using offsetof: %p\n", ptr->buf - offsetof(struct sdshdr, buf));
free(ptr);
return 0;
}
我在struct sdshdr中添加了一个成员,char c。此代码的输出是:
offset: 9, size: 12
sdshdr address: 0x20ce010
buf address: 0x20ce019
calculate using sizeof: 0x20ce00d
calculate using offsetof: 0x20ce010
现在struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
错了,struct sdshdr *sh = (void*)(s-(offsetof(struct sdshdr,buf)));
是对的。