list_entry(ptr, type, member)——知道结构体内某一成员变量地址,求结构体地址
2017-08-28 11:50
295 查看
1 #define list_entry(ptr, type, member) \ 2 ((type *)((char *)(ptr) - (unsigned long)(&((type *)0) -> member)))
解释:
1 在0这个地址看做有一个虚拟的type类型的变量,那么取一个成员再取这个成员的地址,就是这个结构体中这个成员的绝对地址 。
2 这句话的意思是获取一个结构体中一个成员在这个结构体中的偏移。type *0是为了计算地址方便。 意思是在0这个地址看做有一个虚拟的type类型的变量,那么取一个成员再取这个成员的地址,就是这个结构体中这个成员的绝对地址, 由于结构体在地址为0的地方,所以这个成员在这个结构体中的相对位置也是这个值了。ptr可能是这个member的指针,而现在想找这 个member所在结构体的地址,所以这个member的地址应该减去这个member在这个结构体中的偏移。然后返回这个结构体类型。
3 实例分析
1 typedef struct 2 { 3 int i; 4 int j; 5 }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)
相关文章推荐
- list_entry(ptr, type, member)
- 怎样根据结构成员的地址找到结构体的地址(list_entry)
- 对list_entry(ptr, type, member)的理解
- #define list_entry(ptr, type, member)
- #define list_entry(ptr, type, member) \ container_of(ptr, type, member)
- 根据结构体某一成员的地址得到该结构体变量的首地址
- 结构体成员地址在结构体内的偏移
- 类成员变量初始化列表(Member Initialization List)
- 由结构体成员地址计算结构体地址——list_entry()原理详解
- C语言--通过结构体成员的地址获取结构体变量的地址
- 由结构体成员地址计算结构体地址——节点地址的函数list_entry()原理详解
- 通过成员变量地址获取结构体地址
- 成员变量在结构体中的偏移——offsetof(type, member)
- 通过成员变量地址获取结构体地址
- C语言计算一个结构体内成员地址的偏移量的两种方法(代码实例)
- 8) 多级结构数据成员指针memberPtr [原创,泛型编程,自由下载转载,需注明出处]
- 类成员变量初始化列表(Member Initialization List)
- 使用反射动态调用类成员,需要Type类的一个方法:InvokeMember。对该方法的声明如下(摘抄于MSDN)
- 使用结构中的成员变量在oc 中进行数据传递
- 指针用法之一:给定结构体求某变量的偏移量,给出某变量偏移量求结构体首地址