Chinaunix首页 | 论坛 | 博客
  • 博客访问: 571726
  • 博文数量: 107
  • 博客积分: 3079
  • 博客等级: 少校
  • 技术积分: 1306
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-08 00:03
个人简介

emmoblin.github.com

文章分类

全部博文(107)

文章存档

2012年(8)

2011年(15)

2010年(49)

2009年(9)

2008年(26)

分类: LINUX

2008-11-30 11:02:56

list_entry()宏

#define list_entry(ptr, type, member) \
        ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))

    ptr是指向list_head类型链表的指针,type为一个结构,而member为结构type中的一个域,类型为list_head,这个宏返回指向type结构的指针。在内核代码中大量引用了这个宏,因此,搞清楚这个宏的含义和用法非常重要。

  
设有如下结构体定义:
typedef struct xxx
{
     ……(结构体中其他域,令其总大小为size1)
     type1 member;
     ……(结构体中其他域)
}type;


定义变量:
   type a;
   type * b;
   type1 * ptr;
执行:
   ptr=&(a.member);
   b=list_entry(ptr,type,member);
则可使b指向a,得到了a的地址

如何做到的呢?

先看&((type *)0)->member:
把“0”强制转化为指针类型,则该指针一定指向“0”(数据段基址)。因为指针是“type *”型的,所以可取到以“0”为基地址的一个type型变量member域的地址。那么这个地址也就等于member域到结构体基地址的偏移字节数。


再来看 ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))):
(char *)(ptr)使得指针的加减操作步长为一字节,(unsigned long)(&((type *)0)->member)等于ptr指向的member到该member所在结构体基地址的偏移字节数。二者一减便得出该结构体的地址。转换为 (type *)型的指针,大功告成。

阅读(2063) | 评论(0) | 转发(2) |
0

上一篇:GNU C扩展

下一篇:浅析理解__init宏

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