为什么redis使用“sizeof”来计算sdshdr的起始地址

时间:2016-06-21 13:39:58

标签: c redis

在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)));是对的。

0 个答案:

没有答案