#define list_entry(ptr, type, member) \
((type *)((char *)(ptr) - (unsigned long)(&((type *)) -> member)))
解释:
1 在0这个地址看做有一个虚拟的type类型的变量,那么取一个成员再取这个成员的地址,就是这个结构体中这个成员的绝对地址 。
2 这句话的意思是获取一个结构体中一个成员在这个结构体中的偏移。type *0是为了计算地址方便。
意思是在0这个地址看做有一个虚拟的type类型的变量,那么取一个成员再取这个成员的地址,就是这个结构体中这个成员的绝对地址,
由于结构体在地址为0的地方,所以这个成员在这个结构体中的相对位置也是这个值了。ptr可能是这个member的指针,而现在想找这
个member所在结构体的地址,所以这个member的地址应该减去这个member在这个结构体中的偏移。然后返回这个结构体类型。
3 实例分析

 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)

list_entry(ptr, type, member)——知道结构体内某一成员变量地址,求结构体地址的更多相关文章

  1. 对list_entry(ptr, type, member)的理解

    如何根据一个结构体成员的地址.结构体类型以及该结构体成员名获得该结构体的首地址? #define list_entry(ptr, type, member) \ ((type *)((char *)( ...

  2. (转)内核container_of(ptr,type,member) 解析

     container_of(ptr,type,member) 用于在已知结构体里面成员member和该成员指针ptr(就是地址)和结构体类型type, 返回该成员所在的结构体的指针(就是地址), 例如 ...

  3. 由结构体成员地址计算结构体地址——list_entry()原理详解

    #define list_entry(ptr, type, member) container_of(ptr, type, member) 在进行编程的时候,我们经常在知道结构体地址的情况下,寻找其中 ...

  4. Linux中的两个经典宏定义:获取结构体成员地址,根据成员地址获得结构体地址;Linux中双向链表的经典实现。

    倘若你查看过Linux Kernel的源码,那么你对 offsetof 和 container_of 这两个宏应该不陌生.这两个宏最初是极客写出的,后来在Linux内核中被推广使用. 1. offse ...

  5. 结构体内的函数与bfs的情景变量

    关于结构体内的函数,太难的尚且不会用,下面是一个简单一点的结构体内函数的代码 定义这样一个结构体函数之后就能像如下这样使用了 以上为结构体内的简单函数,下面重点来了,关于bfs找最短路由于需要避免走回 ...

  6. struct结构体内存大小

    一. 基本原则 1. struct中成员变量的声明顺序,与成员变量对应的内存顺序是一致的: 2. struct本身的起始存储地址必须是成员变量中最长的数据类型的整倍数,注意是最长的数据类型,而不是最长 ...

  7. C++ struct结构体内存对齐

    •小试牛刀 我们自定义两个结构体 A 和 B: struct A { char c1; char c2; int i; double d; }; struct B { char c1; int i; ...

  8. 通过 struct 成员地址 获取 struct 结构体地址

    1. 问题描述: 现在定义了一个结构体: struct Foo { int a; int b; }; Foo foo; 假如由于函数传参等原因,现在程序只能拿到 foo.b 的地址,这时想通过某种方法 ...

  9. nginx取结构体地址

    linux内核提供了一个container_of()宏,可以根据结构体某个成员的地址找到父结构的地址. #define container_of(ptr, type, member) ({ \ con ...

随机推荐

  1. Codeforces Round #113 (Div. 2) Tetrahedron(滚动DP)

    Tetrahedron time limit per test 2 seconds memory limit per test 256 megabytes input standard input o ...

  2. 设计模式-外观模式(Facade Pattern)

    本文由@呆代待殆原创,转载请注明出处:http://www.cnblogs.com/coffeeSS/ 外观模式简介 外观模式的作用用一句话说就是简化接口,举个例子楼主每次编程的时候都要点开IDE.点 ...

  3. Visual Studio 2017创建XAML文件

    Visual Studio 2017创建XAML文件   在Visual Stuido 2015中,在已经创建好的项目中添加XAML文件,只要右击项目,单击“添加”|“新建项”命令,然后从“添加新项” ...

  4. 关于lower_bound的优先级重载

    今天才知道$lower\_bound$最后有一个优先级参数…… 首先$lower\_bound$中的优先级和序列优先级必须相同才有效 $lower\_bound$中优先级默认的是小于号,也就是说仅当序 ...

  5. 【计算几何】【推导】【补集转化】AtCoder Regular Contest 082 E - ConvexScore

    题意:平面上给你N个点.对于一个“凸多边形点集”(凸多边形点集被定义为一个其所有点恰好能形成凸多边形的点集)而言,其对答案的贡献是2^(N个点内在该凸多边形点集形成的凸包内的点数 - 该凸多边形点集的 ...

  6. 【构造】Gym - 101411F - Figure ans Spots

    在最外围的一圈没有意义,所以全都涂黑,内部贪心地涂成棋盘即可. #include<cstdio> #include<cstring> using namespace std; ...

  7. js流程控制与函数

    流程控制 1.条件语句 分支结构 单向分支 if (条件表达式){ code... } 双向分支 if (条件表达式){ code... }else{ code... } 多向分支 if (条件表达式 ...

  8. PHP5.3魔术方法 __invoke

    这个魔幻方法被调用的时机是: 当一个对象当做函数调用的时候, 如果对象定义了__invoke魔幻方法则这个函数会被调用, class Callme { public function __invoke ...

  9. .Net 有关程序集查找与加载的一点反思

    最近在做一款叫VICA产品,此产品采用了插件机制,插件在运行中加载,插件与插件之间存在依赖关系,所有的插件DLL为方便管理都放置在Plugins的文件夹下统一管理.这种处理方式不自觉的就让我想了解cl ...

  10. 以下内容为Stackoverflow上整理以作纪录

    PRO 用IMG标签 Use IMG plus alt attribute if the image is part of the content such as a logo or diagram ...