我阅读了redis的代码,它定义了一个结构:

typedef struct zskiplistNode {
    robj *obj;
    double score;
    struct zskiplistNode *backward;
    struct zskiplistLevel {
        struct zskiplistNode *forward;
        unsigned int span;
    } level[];
} zskiplistNode;


它创建像这样的节点:

zskiplistNode *zn = zmalloc(sizeof(*zn)+level*sizeof(struct zskiplistLevel));


就是说,如果zn的地址是0x10000,那么&(zn->level[0])0x10000+sizeof(zskiplistNode),则数组的内存地址在struct后面?

最佳答案

zn->level(一个灵活的数组成员)具有一定的固定偏移量w.r.t。 zn:如果zn位于地址0x10000,则zn->level[0]可能位于地址0x10018,因为指针robj将占用一个8字节的字(假设使用64位x86机器),而双精度将占用另一个8字节的单词-并且应将其对齐-指针score将占用另一个单词。因此backward偏移了3个字,即24个字节(即zn->level以十六进制表示)。

顺便说一句,编译器或ABI可能会在您的结构中插入空白(用于对齐或符合ABI)。在您的特定示例中,可能不会(在Linux / x86-64上使用GCC)。

您可能对标准offsetof宏感兴趣,当然对0x18“运算符”也很感兴趣。

10-06 01:29