从kernel里面抠出的一些与宏container_of有关的代码,如下:

1、此宏作用是从结构体的某元素(member)出发,得到结构体的首地址;

2、container_of的参数解释

(1)type:指的是(包含member这个成员元素的结构体)所对应的类型,即(我们要获取首地址的那个结构体)所对应的类型;

(2)member:指的是结构体中的某个元素的名字,我们就是从这个元素出发,得到结构体的首地址。注意这个元素在内核中可能也是结构体。

(3)ptr:指向结构体中member这个元素的指针。

3、offsetof的解释

(1)格式这样看比较明显(->优先级比&高):#define offsetof(TYPE, MEMBER)   (    (size_t)      &( (TYPE *)0 )->MEMBER     )

  • 首先(TYPE *)0 ,然后(TYPE *)0 ->MEMBER,接着&((TYPE *)0 ->MEMBER),最后强制类型转换为size_t类型。

(2)进一步解释

  • 即先将0地址强制转换为(要获取首地址的那个)结构体的指针;
  • 然后获取元素member,进而取其地址。由于结构体的指针指向地址为0,那么元素member的地址就是member元素偏移结构体首地址的偏移量。
  • 由于此时偏移量是以地址形式(就一个数字,或者说指针)呈现的,我们要把它改成int类型,所以来一个强制类型转换。

4、container_of解释

(1)const   typeof(  ((type *)0)->member )*   __mptr = (ptr)

首先获取结构体元素member的的类型,然后定义一个指向此类型的指针_mptr,并赋值为ptr;

(2)(type *)  (  (char *)__mptr   -  offsetof(type, member)   )

首先将_mptr强制转化为char*类型,然后减去偏移量,最后强制转换为结构体类型指针,即返回了结构体首地址。

这里之所以转换为char*类型,是因为减去偏移量时,偏移量是多少,那就减去多少字节。

宏定义函数container_of的解释相关推荐

  1. c/c++宏函数的定义与使用(宏定义函数)(macro definition)

    文章目录 为什么要使用宏函数? 什么是宏 如何使用宏 宏的定义 不带参数的宏 带参数的宏(假参数,不是真正的参数,只是替换而已) 原理 对了,如果宏函数与函数名称相同,优先使用宏定义函数 为什么要使用 ...

  2. Madagascar的宏定义函数--判断整数的奇偶性函数

    Madagascar中自己的宏定义函数判断某个整数的奇偶性,它们都在头文件rsf.h,形式如下: #define SF_ODD(n) ((n) & 1) #define SF_EVEN(n) ...

  3. define宏定义函数及用模板函数实现同样的功能

    最近在看别人的代码的过程中,发现了宏定义代码,由于自己这块之前没有用过,所以编写了示例程序,学习一下宏定义代码. 比如我们现在有一个需求,要实现两个数字交换,这两个数字可能是整型,浮点型或者其他类型, ...

  4. 宏定义函数和普通函数

    宏定义函数: 预处理阶段进行简单的文本替换,没有入栈.出栈.参数传递和函数返回等等工作,执行效率明显高于普通函数,因此,简短并且被频繁调用的函数经常用宏定义函数来代替实现 没有参数检查,会影响程序安全 ...

  5. 宏定义函数与普通函数的区别

    目录 前言 1 宏定义函数与普通函数不同 1.1 编译过程上不同 1.2 执行过程上不同 2 批判分析 3 内联函数 前言 可以在前面的系列文章中看到,FreeRTOS 的 头文件中定义了大量的宏定义 ...

  6. 内联函数和宏定义函数的区别

    1.不同点: 内联函数是在编译时展开,而宏在预编译时展开:在编译的时候,内联函数直接被嵌入到目标代码中去,而宏只是一个简单的文本替换. 内联函数可以进行诸如类型安全检查.语句是否正确等编译功能,宏不具 ...

  7. 关于C语言刷题(#define宏定义函数的常见错误)

    关于C语言刷题(#define宏定义函数的常见错误) 首先我们来先看对#define的定义 define,宏定义,C语言中预处理命令一种.分为无参宏定义和带参宏定义.无参宏定义的一般形式为:#defi ...

  8. Madagascar的宏定义函数--取最值、取整

    和SU类似,Madagascar也有自己的宏定义最值和取整函数,它们都定义在rsf.h头文件中,如下: #define SF_MAX(a,b) ((a) < (b) ? (b) : (a)) # ...

  9. 【C++】宏定义函数指针类型

    1.宏定义不分配内存,变量定义分配内存. 2.宏名和参数的括号间不能有空格 3.宏替换只作替换,不做计算,不做表达式求解 //下面是正确的标准的写法 typedef int(FUNC1)(int in ...

最新文章

  1. java约瑟夫环 循环链表_约瑟夫环_循环链表JAVA解答
  2. vbs 服务器获取输入信息,取得服务器上用户组列表脚本之VBS版
  3. 双轴机械臂中的闭环步进电机平顺控制算法: 42HS48EIS,57HS
  4. c语言case的值能动态修改吗,java中的switch case语句中,case所对应的数目是不确定的,能否动态改变case...
  5. 我在网易云信是如何做运维的?
  6. 甲骨文将Exadata Cloud转化为内部软件包
  7. 指北针邮件工具 v1.5.6.1
  8. 一维FDTD等离子体的Matlab,修正过的一维FDTD等离子体MATLAB代码(公式修正)
  9. 经典线程同步 信号量Semaphore
  10. PYTHON: PYENV, PYVENV, VIRTUALENV – WHAT’S THE DIFFERENCE?
  11. win10 sshsecureshellclient删除profile保存的信息
  12. wdatepicker不显示秒_「超逸酷玩」秒秒测智能健康日历如何正确使用电子墨水屏...
  13. 机器学习笔记(二十九):决策树、信息熵
  14. html文件vbs病毒,又一个VBS病毒源码的解密
  15. 修复pdf字体嵌入问题
  16. yolov5的首次colab运行
  17. 遥感数据存储格式 ----BSQ、 BIL、BIP及相互转换
  18. 示波器测量红外遥控器晶振
  19. 腾讯ai开放平台(智能闲聊)sdk----- python3.X
  20. java实现 mysql导入数据库_Java实现MySQL数据库导入

热门文章

  1. JAVA 数组元素的反转
  2. 浅谈MVC MVP MVVM
  3. 使用Servlet实现用户注册
  4. USACO 1.5.4 Checker Challenge
  5. [转载] New Concept English 1——Lesson 7 Are you a teacher?
  6. Oracle常用的几个父栓
  7. 一个application多个 URL
  8. CentOS新增用户并授予sudo权限
  9. Mybatis 详解--- 一级缓存、二级缓存
  10. linux的apache2.4限定某个目录禁止解析PHP及user_agent与PHP相关配置