(十)Linux内核中的常用宏container_of
Container_of在Linux内核中是一个常用的宏,用于从包含在某个结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变量中某个成员的首地址进而获得整个结构体变量的首地址。
Container_of的定义如下:
#define OffsetOf(type, member) ((unsigned long) &(((type *)0)->member))
#define container_of(p, type, member) ((type *) ((char *)(p) - OffsetOf(type, member)))
1、其实它的语法很简单,只是一些指针的灵活应用,它分两步:
第一步,首先定义一个临时的数据类型(通过(type, member) ((unsigned long) &(((type *)0)->member))获得)member在结构体里的相对偏移地址。
第二步,用 ((type *) ((char *)(p)减去member在结构体中的偏移量,得到的值就是整个结构体变量的首地址(整个宏的返回值就是这个首地址)。
其中的语法难点就是如何得出成员相对结构体的偏移量?
2、通过例子说明,如下:
#include <stdio.h>
#define OffsetOf(type, member) ((unsigned long) &(((type *)0)->member))
typedef struct
{
int num;
char ch;
float fl;
}test_struct; int main(void)
{
printf("offsetof(test_struct, num) = %d\n",
OffsetOf(test_struct, num)); printf("offsetof(test_struct, ch) = %d\n",
OffsetOf(test_struct, ch)); printf("offsetof(test_struct, fl) = %d\n",
OffsetOf(test_struct, fl)); return ;
}
例子输出结果:

其中代码难以理解的地方就是它灵活地运用了0地址。如果觉得&(((type *)0)->member)这样的代码不好理解,那么我们可以假设在0地址分配了一个结构体变量test_struct a,然后定义结构体指针变量p并指向a(test_struct *p = &a),如此我们就可以通过&p->member获得成员member的地址。由于a的首地址为0x0,所以成员member的首地址为0x4。

最后通过强制类型转换(unsigned long)把一个地址值转换为一个整数。
3、 分析完container_of的定义,接下来举个例子来体会一下它的使用方法。
例子,如下:
#include <stdio.h>
#define OffsetOf(type, member) ((unsigned long) &(((type *)0)->member))
#define container_of(p, type, member) ((type *) ((char *)(p) - OffsetOf(type, member))) typedef struct
{
int num;
char ch;
float fl;
}test_struct; int main(void)
{
test_struct init_test_struct = { , 'C', 59.12 }; char *char_ptr = &init_test_struct.ch; test_struct *structs = container_of(char_ptr, test_struct, ch); printf(" test_struct->num = %d\n test_struct->ch = %c\n test_struct->fl = %f\n",
structs->num, structs->ch, structs->fl); return ;
}
输出结果:

由此我们知道:#define container_of(p, type, member) ((type *) ((char *)(p) - OffsetOf(type, member))) ,我们知道结构体type的地址为:结构体type的成员member的地址减去member的相对地址。这里(type *) ((char *)(p)指的是结构体type成员member的地址。
(十)Linux内核中的常用宏container_of的更多相关文章
- Linux内核中的常用宏container_of
Container_of在Linux内核中是一个常用的宏,用于从包含在某个结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变量中某个成员的首地址进而获得整个结构体变量的首地址. Containe ...
- Linux内核中的常用宏container_of其实很简单【转】
转自:http://blog.csdn.net/npy_lp/article/details/7010752 开发平台:Ubuntu11.04 编 译器:gcc version 4.5.2 (Ubun ...
- Linux内核中的常用宏container_of其实很简单
http://blog.csdn.net/npy_lp/article/details/7010752 通过一个结构体变量的地址,求该结构体的首地址. #ifndef CONTAINER_OF #de ...
- 《C预处理》Linux内核中可变参数宏的用法
http://blog.csdn.net/tankai19880619/article/details/12015305
- linux内核中的宏ffs(x)
linux内核中ffs(x)宏是平台相关的宏,在arm平台,该宏定义在 arch/arm/include/asm/bitops.h #define ffs(x) ({ unsigned long __ ...
- Linux内核中双向链表的经典实现
概要 前面一章"介绍双向链表并给出了C/C++/Java三种实现",本章继续对双向链表进行探讨,介绍的内容是Linux内核中双向链表的经典实现和用法.其中,也会涉及到Linux内核 ...
- Linux 内核中的 GCC 特性
https://www.ibm.com/developerworks/cn/linux/l-gcc-hacks/ GCC 和 Linux 是出色的组合.尽管它们是独立的软件,但是 Linux 完全依靠 ...
- 剖析linux内核中的宏---------container_of
#define container_of(ptr, type, member) ({ \ const typeof(((type *)0)->member) * __mptr = (ptr); ...
- Linux内核中常用的数据结构和算法(转)
知乎链接:https://zhuanlan.zhihu.com/p/58087261 Linux内核代码中广泛使用了数据结构和算法,其中最常用的两个是链表和红黑树. 链表 Linux内核代码大量使用了 ...
随机推荐
- [ios][swift]提示框,并自动消失
参考: 提示框:http://blog.csdn.net/gishero/article/details/43941361 提示框自动消失:http://www.cnblogs.com/yemingl ...
- IOS中两个view的切换
在ios中,rootview为PassWordViewController,secondview为SecondViewController,实现在rootview中听过一个跳转按钮实现跳转到secon ...
- 【转】MYSQL入门学习之三:全文本搜索
转载地址:http://www.2cto.com/database/201212/173873.html 一.理解全文本搜索 www.2cto.com 1.MyISAM支持全文本搜索,而Inn ...
- [团队项目]sprint3 & 团队贡献分。
希望各组认真准备,拿出最好的阵容最好的状态,展示一学期的学习与工作成果. 各组注意完成sprint3的博客,写上团队贡献分. 将演示PPT(如果有)和代码上传到github. 截止日期:2016.6. ...
- Dive into python学习笔记
http://woodpecker.org.cn/diveintopython/index.html 1.第一个程序odbchelper.py def buildConnectionString(pa ...
- ResultSetMetaData和DatabaseMetaData实现数据库中属性,属性值,属性所赋值的获取等
----------------------------------------------有些类下面代码中有; public class Test1 { TestDAO t=new TestDAO( ...
- 20150625_Andriod_02_ListView2_多条目显示_选中
android listview 参考地址: http://www.cnblogs.com/zhengbeibei/archive/2013/05/14/3078805.html http://xy ...
- poj1026 Cipher
题目意思可概括为给定集合S = {1,..,n}的一个双射关系f, 求经过k次复合之后元素i对应的元素fk(i) (i∈S). 由于函数是双射,一个原像对应唯一一个像,同样一个像有唯一一个原像,考虑整 ...
- JAVA基础知识之JVM-——类加载器
类加载器负责将.class文件加载到内存,并为其创建java.lang.Class对象,这个对象就代表这个类. 在Java中,通过包名+类名来唯一标识一个类,而在JVM中,要用 类加载器实例+包名+类 ...
- Poj(3522),UVa(1395),枚举生成树
题目链接:http://poj.org/problem?id=3522 Slim Span Time Limit: 5000MS Memory Limit: 65536K Total Submis ...