linux tricks 之 container_of.

发布时间:2016-12-31 7:38:06编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"linux tricks 之 container_of. ",主要涉及到linux tricks 之 container_of. 方面的内容,对于linux tricks 之 container_of. 感兴趣的同学可以参考一下。

linux tricks 之 container_of.

转载:http://blog.chinaunix.net/uid-20608849-id-3027972.html

由于内核中定义了很多复杂的数据结构,而它们的实例中的成员在作为函数参数传递的时,函数中可能需要对它的包含者中的其他的兄弟成员进行处理,这就需要只根据成员地址就可以获取整个结构体变量的地址的操作。container_of提供了这样的操作:

 1 include/linux/kernel.h 2 /** 3  * container_of - cast a member of a structure out to the containing structure 4  * @ptr: the pointer to the member. 5  * @type: the type of the container struct this is embedded in. 6  * @member: the name of the member within the struct. 7  * 8  */ 9 #define container_of(ptr, type, member) ({ \10         const typeof( ((type *)0)->member ) *__mptr = (ptr); \11         (type *)( (char *)__mptr - offsetof(type,member) );})

巧妇难为无米之炊,无论如何,都需要告知container_of该整体结构体变量的类型以及当前成员的指针和成员名。typeof用来获取成员的类型并定义一个临时变量__mptr来存储当前成员的地址。offsetof用来获取当前成员相对于整体结构体地址的偏移。它定义为:

 
1 include/linux/compiler-gcc4.h2 #define __compiler_offsetof(a,b) __builtin_offsetof(a,b)3 4 include/linux/stddef.h5 #ifdef __compiler_offsetof6 #define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)7 #else8 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)9 #endif

如果定义了__compiler_offsetof,则使用Gcc编译器内建的offsetof宏,它的作用和此处定义的offsetof相同。它将0地址作为当前结构的首地址,从而直接通过指针访问成员得到的地址即为偏移。将实际使用的结构体中的成员指针__mptr减去offsetof,就得到了结构体的地址。

 
 1 #include <stdio.h> 2 ...... 3 typedef struct man 4 { 5     char name[32]; 6     unsigned int id;     7     unsigned char age; 8     char address[64]; 9 }man_t;10 11 int main()12 {13     man_t tom = {"Tom", 0, 24, "ShangHai China"};14     man_t *man = NULL;15     16     printf("tom:%p, tom.age:%p, offsetof(man_t, age): %d\n", 17                     &tom, &tom.age, offsetof(man_t, age));18                     19     man = container_of(&tom.age, man_t, age);20     printf("tom.name:%s, tom.id:%d, tom.age:%u, tom.address:%s\n", 21                     man->name, man->id, man->age, man->address);22     23     return 0;24 }

测试结果如下:

1 tom:0xbf85cda4, tom.age:0xbf85cdc8, offsetof(man_t, age): 362 tom.name:Tom, tom.id:0, tom.age:24, tom.address:ShangHai China


上一篇:初次尝试用Kotlin实现Android项目
下一篇:nginx 配置管理 - 简单也复杂

相关文章

相关评论

本站评论功能暂时取消,后续此功能例行通知。

一、不得利用本站危害国家安全、泄露国家秘密,不得侵犯国家社会集体的和公民的合法权益,不得利用本站制作、复制和传播不法有害信息!

二、互相尊重,对自己的言论和行为负责。

好贷网好贷款