原文地址:
http://blog.csdn.net/tigerjibo/article/details/8299589
1.container_of宏
1> Container_of在Linux内核中是一个常用的宏,用于从包含在某个结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变量中某个成员的首地址进而获得整个结构体变量的首地址。
2>接口:
container_of(ptr, type, member)
? ptr:表示结构体中member的地址
? type:表示结构体类型
? member:表示结构体中的成员
通过ptr的地址可以返回结构体的首地址
3> container_of的实现:
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
其实它的语法很简单,只是一些指针的灵活应用,它分两步:
第一步,首先定义一个临时的数据类型(通过typeof( ((type *)0)->member )获得)与ptr相同的指针变量__mptr,然后用它来保存ptr的值。
说明:typeof是GNU C对标准C的扩展,它的作用是根据变量获取变量的类型《typeof关键字在linux 内核中很常见》
第二步,用(char *)__mptr减去member在结构体中的偏移量,得到的值就是整个结构体变量的首地址(整个宏的返回值就是这个首地址)。
关于offsetof的用法可参见offsetof宏的使用。
2.offset宏讲解
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE*)0)->MEMBER)
对这个宏的讲解我们大致可以分为以下4步进行讲解:
1>( (TYPE *)0 ) 0地址强制 "转换" 为 TYPE结构类型的指针;
2>((TYPE *)0)->MEMBER 访问TYPE结构中的MEMBER数据成员;
3>&( ( (TYPE *)0 )->MEMBER)取出TYPE结构中的数据成员MEMBER的地址;
4>(size_t)(&(((TYPE*)0)->MEMBER))结果转换为size_t类型。
宏offsetof的巧妙之处在于将0地址强制转换为 TYPE结构类型的指针,TYPE结构以内存空间首地址0作为起始地址,则成员地址自然为偏移地址。可能有的读者会想是不是非要用0呢?当然不是,我们仅仅是为了计算的简便。也可以使用是他的值,只是算出来的结果还要再减去该数值才是偏移地址。
阅读(641) | 评论(0) | 转发(0) |