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. Linux打包与压缩及tar命令详解

    打包和压缩   在linux中,打包和压缩可以说是两个不同的概念,弄清这两个概念对于我们理解复杂的文件后缀有非常大的帮助 打包 将若干个文件和目录打包在一起变成一个大的文件,这时只是简单的打包,所以一 ...

  2. 体验VS2015 Update 2 的 Android 和 Python

    趁着假期不用加班,又遇到build 2016的劲爆消息--Xamarin免费集成到VS中 所以立马把vs升级到update 2体验一下下(之前也体验过). 在安装的时候也是只勾选了部分,不需要太多(全 ...

  3. 关于异步执行(Async/await)的理解(转发)

    原文地址: http://blog.jobbole.com/85787/ 同步编程与异步编程 通常情况下,我们写的C#代码就是同步的,运行在同一个线程中,从程序的第一行代码到最后一句代码顺序执行.而异 ...

  4. WinServer远程部署系统打包批处理文件

    前言 工作中一直在使用一个部署系统WinServer远程部署系统(RDSystem),部署.回滚都很方便.我们一直都是增量发布或者只更新需要更新的文件,每次发布完之后要整理出一个增量更新包,压缩成zi ...

  5. asp.net mvc项目自定义区域

    前言 直接上干货就是,就不废话了. 使用场景:分离模块,多站点等~~ 一.分离模块 自定义视图引擎,设置视图路径格式 项目结构图 1.Code: 在Global.asax Application_St ...

  6. Gym 100703I---Endeavor for perfection(尺取)

    题目链接 http://codeforces.com/problemset/gymProblem/100703/I Description standard input/outputStatement ...

  7. iOS面试用到的知识点和技术点--第二章

    接着第一章的继续  昨天没有更新,很抱歉 1.Socket编程 以及一些第三方框架Socket-IO GCDAsyncSocket通信框架? 1.使用系统自带的CFsocket 2.第三方Socket ...

  8. 25、ASP.NET MVC入门到精通——Spring.net-业务层仓储

    本系列目录:ASP.NET MVC4入门到精通系列目录汇总 上一节,我们已经把项目框架的雏形搭建好了,那么现在我来开始业务实现,在业务实现的过程当中,不断的来完善我们现有的框架. 1.假设我们来做一个 ...

  9. jQuery弹出关闭遮罩层

    效果体验:http://keleyi.com/keleyi/phtml/jquery/9.htm 完整代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XH ...

  10. TypeScript的4种编译方式

    1.手动编译 1.1.首先找到TypeScript的安装目录,我的在"C:\Program Files (x86)\Microsoft SDKs\TypeScript\1.0".