以下地址文章解释很好

http://blog.chinaunix.net/uid-27122224-id-3277511.html

对下面的结构体分析

1 struct person 
2 { 
3       int age; 
4       int weight; 
5       struct list_head list; 
6 };

遍历的方法中用到的一个重要宏,这个宏可以遍历不同类型的结构体

1 /** 
2  * list_entry - get the struct for this entry 
3  * @ptr: the &struct list_head pointer. 
4  * @type: the type of the struct this is embedded in. 
5  * @member: the name of the list_struct within the struct. 
6  */ 
7 #define list_entry(ptr, type, member) \ 
8      ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
View Code
从person类的链表成员中获取person的方法:
1 struct person *one = list_entry(pos, struct person, list);
View Code

也就是:

1 ((struct person *)((char *)(pos) - (unsigned long)(&((struct person *)0)->list)))
View Code
我慢慢的分解,首先分成两部分(char *)(pos)减去(unsigned long)(&((struct person *)0)- 
>list)然后转 成(struct person *)类型的指针。 
 
(char *)(pos):是将pos由struct list_head*转 成char* ,这个好理解。 
(unsigned long)(&((struct person *)0)->list):先看最里面的(struct person *)0),它是把0 
地址转 成struct person指针,然后(struct person *)0)->list就是指向list变量,之后是 
&((struct person *)0)->list是取这个变量的地址,最后是(unsigned long)(&((struct person 
*)0)->list)把这个变量的地址值变成一个整形数! 
这么复杂啊,其实说白了,这个(unsigned long)(&((struct person *)0)->list)的意思就是取list 
变量在struct person结构中的偏移量。 
用个图形来说(unsigned long)(&((struct person *)0)->list,如下:
而(unsigned long)(&((struct person *)0)->list就是获取这个offset的值。
((char *)(pos) - (unsigned long)(&((struct person *)0)->list))
就是将pos指针往前移动offset位置,即是本来pos是struct list_head类型,它即是list。即是把 
pos指针往struct person结构的头地址位置移动过去,如上图的pos和虚箭头。 
当pos移到struct person结构头后就转 成(struct person *)指针,这样就可以得到struct person 
*变量了。 
posted on 2016-07-18 17:32  人生一世,草木一秋。  阅读(144)  评论(0编辑  收藏  举报