list_entry

list_entry这样定义

                #define list_entry(ptr, type, member) /
                                            ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))

解释:找到成员member所在容器的地址。如果是结构体的话,就是找到结构体成员变量member所在结构体type的地址。

摘抄的解释例子(有修改):

typedef struct
{
     int i;
     int j
} exp;
这个exp结构体占用8个字节.

假设声明一个变量。
                          exp e1;
那么假如已知 e1.j 的地址,想知道 e1 的地址该如何办呢?只要知道 j 在 e1 中的偏移,然后把 j 的地址减去这个偏移就是 e1 的地址了。在这里, i 占据的前4个字节,所以 j 占据了5-8的字节。

现在我们用 list_entry 来解释一下。
                          int *p = e1.j;
假设 e1 的地址是 0x100,那么 p 就是 0x104。可是如何才能比较方便的知道 p 减去 4 就是 e1 的地址呢?尤其是我们可能有时候不知道 exp 这个结构体里面具体什么样子的。使用  list_entry(p, exp, j),则变成:
                         (exp *)((char *)p-(unsigned long)(&((exp *)0)->j))
(exp *)0 在 0 地址上面建立 8 个字节的 exp 结构体, ->j 取出这个0地址上exp结构体里的j成员, &((exp *)0)->j) 把这个成员地址取出来,由于 j 在这个结构体里是在5-8字节,所以从0地址数5个字节就是 j 所在的位置。这种方法省去了我们需要预先知道结构体具体什么样子,结构体里成员的位置怎么安排的。p 的地址再减去我们刚算出来j所在的位置,就得到 e1 的地址。也就是:
                         &e1 == list_entry(p, exp, j)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值