我是靠谱客的博主 微笑蓝天,最近开发中收集的这篇文章主要介绍list_for_each_entry(pos, head, member)的内幕,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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)的内幕所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(48)

评论列表共有 0 条评论

立即
投稿
返回
顶部