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结构的指针。在内核代码中大量引用了这个宏,因此,搞清楚这个宏的含义和用法非常重要。
这个宏到底有什么作用:
简单的说他的作用是 通过一个结构体(通常为一个宿主结构,该结构中包含一个struct list, 当然也可以为其它, 通过该list当所有宿主连接起来)中的一个成员的地址来获得这个该结构体的地址,有了这个地址,就可以访问结构的其它成员
设有如下结构体定义:
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)使得指针的加减操作步长为一字节,注意(char *)绝对不能少, 假设没有这个强制转换,那么ptr就是其它类型(如int型) 减去得到的偏移(假如为12),最后的结果将是ptr-(12*4)因为int型占4个字节,所以(char *)不能少
,(unsigned long)(&((type *)0)->member)等于ptr指向的member到该member所在结构体基地址的偏移字节数。二者一减便得出该结构体的地址。转换为(type *)型的指针,
应用举例:
如建立一个window的list
typedef struct
{
struct list head;
char * wndname;
int x;
int y;
}sWnd;
知道list 再通过list_entry这个宏就可以得到每个window的结构体地址,从而得到window的x, y坐标.
D调漫步 于 2011-08-05 09:07:41发表:
路过
xiaoxizmj 于 2010-01-20 11:38:51发表:
闪过
bourne1209 于 2009-03-23 16:44:17发表:
bourne1209 于 2009-03-23 16:43:31发表:
一直没搞明白,今天总算是有点开窍了/(5ty(
Toad 于 2009-01-07 11:20:13发表:
开过
Austria 于 2009-01-06 18:09:01发表:
闪过哈