以下地址文章解释很好
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)))
从person类的链表成员中获取person的方法:
1 struct person *one = list_entry(pos, struct person, list);
也就是:
1 ((struct person *)((char *)(pos) - (unsigned long)(&((struct person *)0)->list)))
我慢慢的分解,首先分成两部分(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
*变量了。