神奇的宏 container_of()
2016-06-30 15:19
1021 查看
内容翻译自 http://radek.io/2012/11/10/magical-container_of-macro/
当你开始阅读linux内核的代码的时候,你最终会遇到这个神奇的宏。这个宏是做什么的?
三个参数:ptr, type,member, 分别为:成员的指针,包含这个成员的容器的类型,这个成员的名字返回值:一个指针,指向包含这个成员的容器,如下图
这个宏在已知成员名字及指针,想找到包含自己的结构体的指针的时候很有用(废话),什么时候需要呢?比如在使用c语言写一个适用性强的链表的时候
这个宏是如何实现的?
#define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );})
接下来逐步解释
表达式中的声明/语句
GNU 对C语言有一个扩展,名字为braced-group within expression,{}里面的整个表达式的值是最后一个声明的值。编译器计算evaluate整个{},以最后一个声明/语句作为整个表达式的值。下面的例子结果是5
int x = ({1; 2;}) + 3; printf("%d\n", x);
typeof()
这是一个非标准的 GNU C 扩展. 返回唯一参数的类型. 这个宏的语义在http://gcc.gnu.org/onlinedocs/gcc/Typeof.html中与具体描述int x = 5; typeof(x) y = 6; printf("%d %d\n", x, y);
解引用 零指针
获取零指针的成员的类型或者取成员的地址时候并不会崩溃。因为表达式并不会被计算,编译器只关心类型。取成员地址的时候,取出的是在结构体中的偏移地址。struct s { char m1; char m2; }; /* This will print 1 */ printf("%d\n", &((struct s*)0)->m2);
下面两个定义是等价的
typeof(((struct s *)0)->m2) c; char c;
offsetof(st, m)
其实现方法已经在上文中提到了。这个宏在stddef.h中,是标准库的一部分。但是内核没有标准库,下面是内核里的(messy)实现#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
返回名为MEMBER成员在TYPE类型结构体中的偏移位置.
放在一起
#define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );})
结合以上已经非常容易理解
相关文章推荐
- Linux socket 初步
- Linux Kernel 4.0 RC5 发布!
- linux lsof详解
- linux 文件权限
- Linux 执行数学运算
- 10 篇对初学者和专家都有用的 Linux 命令教程
- Linux 与 Windows 对UNICODE 的处理方式
- Ubuntu12.04下QQ完美走起啊!走起啊!有木有啊!
- 解決Linux下Android开发真机调试设备不被识别问题
- 运维入门
- 运维提升
- Linux 自检和 SystemTap
- 神器SystemTap
- Ubuntu Linux使用体验
- c语言实现hashmap(转载)
- Linux 信号signal处理机制
- linux下mysql添加用户
- Scientific Linux 5.5 图形安装教程