linux内核中offsetof与container_of的宏定义

#define offsetof(TYPE, MEMBER)    ((size_t) &((TYPE *)0)->MEMBER)

/** 
* container_of - cast a member of a structure out to the containing structure 
* @ptr:        the pointer to the member. 
* @type:       the type of the container struct this is embedded in. 
* @member:     the name of the member within the struct. 
* */

#define container_of(ptr, type, member) ({                      \ 
const typeof( ((type *)0)->member ) *__mptr = (ptr);    \ 
(type *)( (char *)__mptr - offsetof(type,member) );})

offsetof含义:获取结构体中某个成员变量相对于结构体首地址的内存位置偏移;

container_of含义:根据结构体中某个成员变量的内存地址获取结构体的内存首地址。

offsetof宏详解:

#define offsetof(TYPE, MEMBER)    ((size_t) &((TYPE *)0)->MEMBER)

1)、参数TYPE为结构体的类型定义,MEMBER为结构体成员变量名称;

2)、实现方法比较取巧:将0强制转化TYPE类型的指针,然后对MEMBER变量取址;

3)、代码示例:

typedef struct

{

  int a;

  char b;

  void *c;

} off_struct_s;

printf("offset a:%d b:%d c:%d\n", offsetof(off_strcut_s, a), offsetof(off_strcut_s, b), offsetof(off_strcut_s, c));

最终结果为:offset a:0 b:4 c:8

container_of宏详解:

#define container_of(ptr, type, member) ({                      \ 
const typeof( ((type *)0)->member ) *__mptr = (ptr);    \ 
(type *)( (char *)__mptr - offsetof(type,member) );})

1)、参数ptr为结构体成员的内存地址,type为结构体类型定义,member为结构体成员变量名称;

2)、typeof为gun编译器系列的内置函数,函数返回当前变量的类型;

3)、const typeof( ((type *)0)->member ) *__mptr = (ptr); 这行定义了一个member类型的指针变量__mptr,并且值初始化为ptr(注意:这里type也是0强制转换);

4)、(type *)( (char *)__mptr - offsetof(type,member) );

这行则是将结构体成员变量的内存地址减去此成员变量与结构体首地址的偏移(offsetof前面已讲解),即为结构体的内存首地址;

5)、代码示例:

off_struct_s stru;

void *ptr;

ptr = (void *)(container_of(&stru.c, off_struct_s, c));

printf("stru_addr:%p container_addr:%p\n", &stru, ptr);

运行结果必然是&stru与ptr的内存地址是一样的,这个例子只是做一个证明,实际使用时肯定是先不知道结构体首地址的,需要由结构体变量地址计算结构体首地址。

其实总结起来很简单,要想根据一个结构体变量的指针计算出结构体本身的指针,只需要当前变量指针减去变量到结构体首的偏移(base = ptr - offset)。

linux中offsetof与container_of宏定义的更多相关文章

  1. Linux Kernel代码艺术——系统调用宏定义

    我们习惯在SI(Source Insight)中阅读Linux内核,SI会建立符号表数据库,能非常方便地跳转到变量.宏.函数等的定义处.但在处理系统调用的函数时,却会遇到一些麻烦:我们知道系统调用函数 ...

  2. C中的预编译宏定义

     可以用宏判断是否为ARC环境 #if _has_feature(objc_arc) #else //MRC #endif C中的预编译宏定义 -- 作者: infobillows 来源:网络 在将一 ...

  3. iOS --- 总结Objective-C中经常使用的宏定义(持续更新中)

    将iOS开发中经常使用的宏定义整理例如以下,仅包括Objective-C. 而对于Swift,不能使用宏,则能够定义全局函数或者extension.请參考博客iOS - 总结Swift中经常使用的全局 ...

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

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

  5. (转)offsetof与container_of宏[总结]

    1.前言 今天在看代码时,遇到offsetof和container_of两个宏,觉得很有意思,功能很强大.offsetof是用来判断结构体中成员的偏移位置,container_of宏用来根据成员的地址 ...

  6. offsetof与container_of宏[总结]

    1.前言 今天在看代码时,遇到offsetof和container_of两个宏,觉得很有意思,功能很强大.offsetof是用来判断结构体中成员的偏移位置,container_of宏用来根据成员的地址 ...

  7. offsetof与container_of宏分析

    offsetof宏:结构体成员相对结构体的偏移位置 container_of:根据结构体成员的地址来获取结构体的地址 offsetof 宏 原型: #define offsetof(TYPE, MEM ...

  8. VC中预处理指令与宏定义详解

    刚接触到MFC编程的人往往会被MFC 向导生成的各种宏定义和预处理指令所吓倒,但是预处理和宏定义又是C语言的一个强大工具.使用它们可以进行简单的源代码控制,版本控制,预警或者完成一些特殊的功能. 一个 ...

  9. 对offsetof、 container_of宏和结构体的理解

    offsetof 宏 #include<stdio.h> #define offsetoff(type, member)      ((int)&((type*)0)->me ...

随机推荐

  1. React Native at first sight

    what is React Native? 跟据官方的描述, React Native是一套使用 React 构建 Native app 的编程框架. 推出不久便引发了广泛关注, 这也得益于 Java ...

  2. 基于Metronic的Bootstrap开发框架经验总结(10)--优化Bootstrap图标管理

    在基于Bootstrap开发的项目中,鲜艳颜色的按钮,以及丰富的图表是很吸引人的特点,为了将这个特点发挥到极致,可以利用Bootstrap图标抽取到数据库里面,并在界面中进行管理和使用,这样我们可以把 ...

  3. ipsec IP安全策略操作 win7

    //禁止 win7 连接 public static void BannedWINRunCmd() { string str = Console.ReadLine(); System.Diagnost ...

  4. Verilog学习笔记基本语法篇(十二)········ 编译预处理

    h Verilog HDL语言和C语言一样也提供编译预处理的功能.在Verilog中为了和一般的语句相区别,这些预处理语句以符号"`"开头,注意,这个字符位于主键盘的左上角,其对应 ...

  5. DDD开发框架ABP之本地化资源的数据库存储扩展

    在上一篇<DDD开发框架ABP之本地化/多语言支持>中,我们知道,ABP开发框架中本地化资源存储可以采用XML文件,RESX资源文件,也提供了其他自定义的存储方式的扩展接口.ABP框架默认 ...

  6. javascript函数调用的各种方法!!

    在JavaScript中一共有下面4种调用方式: (1) 基本函数调用 (2)方法调用 (3)构造器调用 (4)通过call()和apply()进行调用 1. 基本函数调用 普通函数调用模式,如: J ...

  7. 屌丝giser成长记-研一篇(上)

    2011年本科毕业之后,我选择了保研GIS研究生,继续了我的GIS研究生涯,读研的童鞋们注意了,读研选择什么样的导师很重要,因为不同的导师有不同的人脉,从浅一点的来说,导师手头的开发项目多的话,你自己 ...

  8. 【超全整理】J2EE集成开发环境MyEclipse使用心得汇总

    一.首先我们为什么需要MyEclipse? 下面允许我做一些简要的介绍: 应该大家都知道另一个MyEclipse的近亲——Eclipse的优点:免费.程序代码排版功能.有中文汉化包.可增设许多功能强大 ...

  9. 利用UICollectionViewFlowLayout的隐式动画实现UICollectionView的layout的动画调整(外加放大指定cell效果)

    前几天在gitHub看到个不错的效果,就是DaiExpandCollectionView,效果如图:   所以赶紧下下来源码看看他怎么实现的,打开源码看了半天,发现他没写什么关于动画的代码啊... 经 ...

  10. Android系统的五种数据存储形式(一)

    Android系统有五种数据存储形式,分别是文件存储.SP存储.数据库存储.contentprovider 内容提供者.网络存储.其中,前四个是本地存储.存储的类型包括简单文本.窗口状态存储.音频视频 ...