Chinaunix首页 | 论坛 | 博客
  • 博客访问: 301710
  • 博文数量: 43
  • 博客积分: 3000
  • 博客等级: 中校
  • 技术积分: 790
  • 用 户 组: 普通用户
  • 注册时间: 2007-04-06 15:15
文章分类

全部博文(43)

文章存档

2011年(11)

2010年(14)

2009年(7)

2008年(11)

我的朋友

分类: LINUX

2011-01-12 01:01:05

//该宏位于include/linux/kernel.h

1.定义格式

/**        

 * 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) );})

作用:就是根据一个结构体变量中的一个域成员变量的指针来获取指向整个结构体变量的指针。

       例:

       struct demo_struct

       {

              type1 member1;

              type2 member2;

              type3 member3;

       }

       struct demo_struct demo1,*pdemo;

       type2 * demo_member2=demo1.member2;

       如果要得到demo1的指针,可以使用该宏:

              pdemo=container_of(demo_member2,struct demo_struct,member2);

2.宏运行机理解析

       typeofGNU C对标准C的扩展,它的作用是根据变量获取变量的类型。将上例中的宏按照宏定义进行展开,如下:

       1     pdemo=({ \

2       const typeof(((struct demo_struct *)0)->member2)  *__mptr=(demo_member2); \

       3        (struct demo_struct *)((char *)__mptr-offsetof(struct demo_struct, member2));\

4         })

       从上面定义来看,代码中的第2行的作用是首先使用typeof获取结构体域变量member2的类型为 type2,然后定义了一个type2指针类型的临时变量__mptr,并将实际结构体变量中的域变量的指针demo_member2的值赋给临时变量__mptr

       2行代码实际上类似下面定义:

              const type2 * __mptr=demo_member2;

       这里((struct demo_struct *)0)比较巧妙,它指的是struct demo_struct 型变量地址为基地址,偏移量为0的地址,实际上就是struct demo_struct 型变量地址。

       3行代码中,(char *)__mptr转换为字节型指针。(char *)__mptr - offsetof(type,member) )用来求出结构体起始地址(为char *型指针),然后(type *)( (char *)__mptr - offsetof(type,member) )(type *)作用下进行将字节型的结构体起始指针转换为type *型的结构体起始指针。

       其中,offsetof宏定义如下:

              #define offsetof(TYPE, MEMBER)  ((size_t) &(((TYPE *)0)->MEMBER)

       可以看出,该宏就是计算出TYPE变量中MEMBER成员基地址。该宏运行机理如下:

l         ( (TYPE *)0 ) 将零转型为TYPE类型指针;

l         ((TYPE *)0)->MEMBER 访问结构中的数据成员;

l         &( ( (TYPE *)0 )->MEMBER )取出数据成员的地址;

l         (size_t)(&(((TYPE*)0)->MEMBER))结果转换类型。

该宏巧妙之处在于将0转换成(TYPE*),如果结构体以内存空间首地址0作为起始地址,则成员地址自然为偏移地址;

__mptr - offsetof(struct demo_struct, member2)

type1 member1

type2 member2

 

type3 member3

offsetof(type,member)__mptr

__mptr - offsetof(struct demo_struct, member2)

type1 member1

type2 member2

 

type3 member3

offsetof(type,member)__mptr

阅读(679) | 评论(1) | 转发(0) |
0

上一篇:Linux SCSI 子系统剖析

下一篇:Android ANR

给主人留下些什么吧!~~

chinaunix网友2011-03-09 09:11:10

很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com