container_of()这个宏定义的功能是根据一个已知结构体成员的指针和变量名得出宿主结构体的地址

为方便理解和描述,本文中将已知的结构体成员叫做功能成员,它所在的结构体叫做宿主结构体。
先来分析一下参数:
ptr:指向功能成员的指针,存放功能成员的地址
type:宿主结构体的类型
member:功能成员在结构体中的表示(变量名)
container_of(ptr, type, member)的完整宏展开:
container_of(ptr, type, member) ({
const typeof( ((type*)0)->member ) *__mptr = (ptr) ;
(type*)( (char *)__mptr - offsetof(type, member) ) ; })
第2行,可能大伙看得有点蒙,先来分解一下这个语句的结构
我们定义一个变量的格式是:修饰符+变量类型+变量名 = 右值;
修饰符            变量类型                                变量名     右值
const     typeof( ((type*)0)->member )    *__mptr =  (ptr) ;
现在看明白了吗,抛开具体细节,“typeof( ((type*)0)->member )”代表的是一种数据类型,那么它是什么样的数据类型呢?
((type*)0):它把0转换为一个type类型(也就是宿主结构体类型),为什么要这样做,且看后文
((type*)0)->member:这个0指针指向结构体中的member成员
typeof是gcc的c语言扩展保留字,用于获取变量的类型
 typeof( ((type*)0)->member )    *:得出member的数据类型
所以,第2行的结果就是定义一个指向member的指针,并赋值为ptr
第3行,我们先看后半部分 offsetof(type, member);
offsetof定义在/include/linux/stddef.h中
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
根据前面的讲解可以知道:&((TYPE *)0)->MEMBER获得MEMBER的地址,再转为size_t类型作为一个整数,由于此时&stu=0,因为结构体的基地址为0,所以MEMBER自然为其在结构体中的偏移地址。当然也可以把0换成1,这时&stu=1,要想得出功能成员相对于宿主结构体的偏移量还得在后面减去1,所以用0的好处就是使得功能成员的地址是相对于宿主结构体的偏移量。回到第2行,将0改为其他的任意正整数如“1”,并不影响最后的结果,因为在第二行中的目的仅仅是获得member的数据类型而已。
(char *)__mptr - offsetof(type, member):用第2行获得的结构体成员地址减去其在结构体中的偏移值便可得到宿主结构体的地址
可能有些同学觉得疑问,为什么要把__mptr转换为char类型的指针呢,C语言中,一个指向特定数据类型的指针减1,实际上减去的是它所指向数据类型的字节大小sizeof(data),所以这里要把它转换成char类型,不然得不出正确结果
(type*)( (char *)__mptr - offsetof(type, member) ) 最后把地址转换成宿主结构体的类型type
由此,container_of()实现了根据一个已知结构体成员的指针和变量名得出宿主结构体的地址的功能
转载:http://blog.csdn.net/u010415192/article/details/49523143

container_of(ptr, type, member)宏定义解析相关推荐

  1. #define list_entry(ptr, type, member) \   container_of(ptr, type, member)

    2019独角兽企业重金招聘Python工程师标准>>> #define container_of(ptr, type, member) ({            \     con ...

  2. matlab 类似宏定义,比较全面的宏定义解析

    宏定义 宏定义是C提供的三种预处理功能的其中一种,这三种预处理包括:宏定义.文件包含.条件编译. 参数 不带参数 宏定义又称为宏代换.宏替换,简称"宏". 格式: #define ...

  3. Linux 内核中 likely 与 unlikely 的宏定义解析

    在 2.6 内核中,随处能够见到 likely() 和 unlikely() 的身影,那么为什么要用它们?它们之间有什么差别? 首先要明白: if(likely(value)) 等价于 if(valu ...

  4. linux中offsetof与container_of宏定义

    linux内核中offsetof与container_of的宏定义 #define offsetof(TYPE, MEMBER)    ((size_t) &((TYPE *)0)->M ...

  5. offset linux,Linux 宏定义之 offsetof 与 container_of(十九)

    今天我们来看看 Linux 中的两个经典的宏:offsetof 与 container_of.下来我们先来看看它们两个的宏定义,如下#ifndef offsetof #define offsetof( ...

  6. container_of宏定义分析---linux内核

    问题:如何通过结构中的某个变量获取结构本身的指针??? 关于container_of宏定义在[include/linux/kernel.h]中: /*_* * container_of - cast ...

  7. C linux 宏定义的使用

    //在内核代码中使用了大量的inline的内联函数的声明,但是它的字面意思和#define的用法貌似很相似但是 //又有不同的区别,虽然极大的提上了代码的运行效率,但是增加了代码的长度,和对cpu指令 ...

  8. Linux内核源码中使用宏定义的若干技巧

    在C中,宏定义的概念虽然简单,但是真要用好却并不那么容易,下面从Linux源码中抽取一些宏定义的使用方法,希望能从中得到点启发: 1. 类型检查 比如module_init的宏定义: 点击(此处)折叠 ...

  9. contain_of宏定义

    Container_of在Linux内核中是一个常用的宏,用于从包含在某个结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变量中某个成员的首地址进而获得整个结构体变量的首地址. 实现方式: co ...

最新文章

  1. 二叉树的基本特性和二叉树的几种基本操作的机制_笃学不倦|二叉树(一)
  2. 第十三周项目-交通工具类程序
  3. 教你写一个可以找到.m文件所有接口名的命令行工具
  4. 多功能时钟电路的设计框图_一种病理组织漂片多功能一体机的设计
  5. 将php源码修改成存在注入的源码,天融信关于ucms系统存在代码注入漏洞的分析...
  6. android content item,Android中ContentProvider的应用实例
  7. jsp显示服务器路径下的图片,jsp 从服务器获取图片路径
  8. 中国大陆物联网驶入快车道 台商抢上车
  9. 20180921 su与sudo命令、限制root用户通过ssh远程登录
  10. 【树莓派】iptables相关配置
  11. jQuery hasAttr检查元素是否有属性[重复]
  12. Mapbar 地图 API 概念   技术文档
  13. mac上设置sudo不要密码
  14. 机器学习之amp;amp;Andrew Ng课程复习--- 聚类——Clustering
  15. 手机应用宝占用了8G
  16. Abaqus GUI界面解决中文乱码问题(插件中文乱码也适用)
  17. English写作-如何运用such as、for example、etc.、i.e.
  18. “大多数”餐馆收银系统被用于盗用信用卡信息的恶意软件感染
  19. 使用Excel数据分析工具进行多元线性回归分析
  20. 天津市南洋工业学校计算机应用,一、计算机应用技术技能

热门文章

  1. ubuntu server 10.04 LTS(64位)装不了花生壳的解决方法
  2. 单引号(')和双引号()
  3. C语言长度为0的数组
  4. UA MATH567 高维统计专题1 稀疏信号及其恢复5 LASSO的估计误差
  5. Java LinkedList类基本用法
  6. win32 断言函数和转换到COFF期间失败错误
  7. 图解JDK命令行工具实例教程
  8. (重要)java都是值传递,与对象形参所指向的对象改变,其实参所指向的对象也相应改变并不矛盾(2011年9.30日一天写的两个程序的总结结果)...
  9. 对Dev的GridControl/GridView控件进行分组并展开操作
  10. [sh]top添加到crontab不生效问题解决