概述
list_for_each_entry(pos, head, member)是一个遍历链表的操作,但是从中涉及到的小函数很多,想要彻底高清除,需要下一点功夫。
下面一步一步的分解该宏定义。抽丝剥茧的看看这个宏定义到底最后定义成什么了。
#define list_for_each_entry(pos, head, member)
for (pos = list_entry((head)->next, typeof(*pos), member);
&pos->member != (head);
pos = list_entry(pos->member.next, typeof(*pos), member))
宏定义如上,里面关键的宏定义 list_entry是什么呢?恩,是它
#define list_entry(ptr, type, member)
container_of(ptr, type, member)
那么, list_for_each_entry最终简化成
#define list_for_each_entry(pos, head, member)
for (pos = container_of((head)->next, typeof(*pos), member);
&pos->member != (head);
pos = container_of(pos->member.next, typeof(*pos), member))
好了,可以看出,整个宏定义的关键就在于 container_of上面。而这个宏定义如下:
#define container_of(ptr, type, member) ({
const typeof( ((type *)0)->member ) *__mptr = (ptr);
(type *)( (char *)__mptr - offsetof(type,member) );})
这个定义看起来特别复杂,但是一步一步展开后,它原理特别简单。分析以下分为两步( 注意:其中member是type类型中的一个变量,还有ptr是指向member类型的指针)
1:定义一个*__mptr等于ptr。其中typeof的作用就是不用定义类型直接可以推断出此类型,详细信息可以到网上搜一下。
2:根据offsetof(type,member) 是求偏移量的。然后用*__mptr减去偏移量。那不就是结构体type类型所对应的地址么?
用如下例子可以看出
#include <stdio.h>
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container_of(ptr, type, member) ({
const typeof( ((type *)0)->member ) *__mptr = (ptr);
(type *)( (char *)__mptr - offsetof(type,member) );})
struct test_struct {
int num;
char ch;
float f1;
};
int main(void)
{
struct test_struct *pos;
struct test_struct init_struct ={12,'a',12.3};
int *ptr_ch1 = &init_struct.num;
pos = container_of(ptr_ch1,struct test_struct,num);
printf("%p----%pn",pos,&init_struct);
char *ptr_ch2 = &init_struct.ch;
pos= container_of(ptr_ch2,struct test_struct,ch);
printf("%p----%pn",pos,&init_struct);
float *ptr_ch3 = &init_struct.f1;
pos = container_of(ptr_ch3,struct test_struct,f1);
printf("%p----%pn",pos,&init_struct);
printf("test_struct->num =%dn",pos->num);
printf("test_struct->ch =%cn",pos->ch);
printf("test_struct->ch =%fn",pos->f1);
return 0;
}
得到的结果:
0xbf942ca4----0xbf942ca4
0xbf942ca4----0xbf942ca4
0xbf942ca4----0xbf942ca4
test_struct->num =12
test_struct->ch =a
test_struct->ch =12.300000
可知我们的思路是正确的。
一般条件下,调用函数中的member为list_head类型,那list_for_each_entry的函数就可以用以下内容概括了:
即根据list_head的遍历找出下一个list_head。然后推断出整个pos的类型第地址。以便求出里面的数据
最后
以上就是微笑蓝天为你收集整理的list_for_each_entry(pos, head, member)的内幕的全部内容,希望文章能够帮你解决list_for_each_entry(pos, head, member)的内幕所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复