我阅读了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
“运算符”也很感兴趣。