linux内核中的list_for_each_entry函数

通过结构体成员获取结构体地址

代码仅作解释,不能直接运行

// 结构体 :该结构体里面有一个节点 node,该节点会插入到 一个链表里面
struct input_handler {
	int minor;
	struct list_head	node;
};


// 链表 
struct list_head {
	struct list_head *next, *prev;   
};
	
int main(void)
{
	// 实化一个链表、创建一个结构体指针 -- 忽略链表初始化和节点插入过程,假设这些都已经完成
	struct input_handler *handler;
	struct list_head input_handler_list;


	/* input_handler_list链表里面链接的节点 是 handler结构体里的一个成员 -- node
	   参数①:结构体指针
	   参数②:链表头节点地址
	   参数③:节点名字 */
	list_for_each_entry(handler, &input_handler_list, node)
}


static inline void prefetch(const void *x) {;}


// ----------- 分析1  list_for_each_entry(pos, head, member)	 -------------------------------//
#define list_for_each_entry(pos, head, member)				\
	for (pos = list_entry((head)->next, typeof(*pos), member);	\
	     prefetch(pos->member.next), &pos->member != (head); 	\
	     pos = list_entry(pos->member.next, typeof(*pos), member))

	/*  
		参数1:pos  = handler 结构体指针 	【解释:pointer of struct】
		参数2: head =  &input_handler_list	【链表头节点的地址,head就变成了一个指针 】
		参数3:member = node				【节点的名字】

	【1】for结构的初始化:得到了链表中 第一个节点的 父结构体指针,得到结构体指针就能操作该结构体
		 pos = list_entry(  (head)->next, typeof(*pos), member  );
	    【1.1】分析list_entry	
			 
	*/



// ----------- 分析2 list_entry(ptr, type, member)	 -------------------------------//
#define list_entry(ptr, type, member) \
	container_of(ptr, type, member)
	/*  
		参数1:ptr  = (head)->next 						【链表头节点的下一个节点】
		参数2: type = typeof(*pos) = typeof(*handler)	【得到结构体类型】
		参数3:member = node							【节点的名字】

	【1.1】list_entry的目的似乎是为了将参数的表达变的简单后,再进行具体操作
		   container_of(ptr, type, member)	
		  【1.1.1】分析container_of
	*/




// ----------- 分析3 container_of(ptr, type, member)  -------------------------------//
#define container_of(ptr, type, member) ({			\
	const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
	(type *)( (char *)__mptr - offsetof(type,member) );})
	/*  
		参数1:ptr  = (head)->next 						【链表头节点的下一个节点】
		参数2: type = typeof(*pos) = typeof(*handler)	【得到结构体类型】
		参数3:member = node							【节点的名字】

	【1.1.1】
	 第一行分析
	 	简化成:const XXX *__mptr = (ptr); 等价于 const struct list_head *__mptr = input_handler_list->next;
	 	第一行定义了一个指针并初始化,初始化结果就是该指针就变成 head->next指针,存储的是节点的地址
	 		指针类型见下分析:	
			【(type *)0】将0强转为一个地址,地址(0x0000)变成一个type类型结构体的首地址,这里的type就是input_handler
			【typeof( ((type *)0)->member )】 取得这个type类型结构体中名为member的成员 的类型, 这里的member就是node
	第2行分析:
		简化成:(type *)( 地址 ); 等价于 struct input_handler *( 地址 )
		【 (char *)__mptr 】将__mptr从结构体指针转化为无符号整形指针,(char *)__mptr = 节点的地址
							offsetof得到的是一个无符号整形值
		最后结果就是  pos = list_entry( (head)->next, typeof(*pos), member ); 
						  = container_of(ptr, type, member);
						  = ({ const struct list_head *__mptr = input_handler_list->next;
							  (struct input_handler *)( 地址 )	
			*/




// ----------- 分析4 offsetof(TYPE, MEMBER)  -------------------------------//
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
	/*  
		参数2: type = typeof(*pos) = typeof(*handler)	【得到结构体类型】
		参数3:member = node							【节点的名字】

		【(TYPE *)0)->MEMBER】 取结构体中的成员
		【&(TYPE *)0)->MEMBER】取成员地址,由于该结构体地址从0x0开始,所以成员地址就是偏移地址
		【(size_t)addr】将获得的地址强制转化为 无符号整型 size_t
	*/

宏定义使用

代码可直接运行

/*  */
#include <stdio.h>		// ptintf; scanf	
#include <stdlib.h>	// 分配内存,释放内存


// 不要少了() -- ({})
#define XXX ({ \
	int i=5;    \
	(int)(i-1);	})

int main(int argc, char **argv)
{

	int p;
	int t;
	p = XXX;


// 不要少了() -- ({})
	t = ({ 					
			int j=10;
			(int)(j-1);	
		 });
		
	printf("%d\n\r",p);
	printf("%d\n\r",t);
	return 0;
}

jj

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值