linux 的list_for_each_entry

linux的宏定义提高了代码的简洁性,但有时候的命名不够完美。比如list_for_each_entry,看名字只知道是遍历list,但一看里面的三个变量参数,有点懵逼。

/**

* list_for_each_entry - iterate over list of given type

* @pos: the type * to use as a loop cursor.

* @head: the head for your list.

* @member: the name of the list_head within the struct.

*/

#define list_for_each_entry(pos, head, member) \

for (pos = list_first_entry(head, typeof(*pos), member); \

!list_entry_is_head(pos, head, member); \

pos = list_next_entry(pos, member))

谁是given type? 被遍历的是谁?咋看看不出来。

/**

* list_first_entry - get the first element from a list

* @ptr: the list head to take the element from.

* @type: the type of the struct this is embedded in.

* @member: the name of the list_head within the struct.

*

* Note, that list is expected to be not empty.

*/

#define list_first_entry(ptr, type, member) \

list_entry((ptr)->next, type, member)

这个宏的comments解释说是获取一个list的第一个元素。 但是一看宏定义有点懵,怎么又来一个宏在里面?

/**

* list_entry - get the struct for this entry

* @ptr: the &struct list_head pointer.

* @type: the type of the struct this is embedded in.

* @member: the name of the list_head within the struct.

*/

#define list_entry(ptr, type, member) \

container_of(ptr, type, member)

这个宏定义看解释是获取当前entry的所属结构体,又来一个宏:

  1. /**

  2. * container_of - cast a member of a structure out to the containing structure

  3. * @ptr: the pointer to the member.

  4. * @type: the type of the container struct this is embedded in.

  5. * @member: the name of the member within the struct.

  6. *

  7. * WARNING: any const qualifier of @ptr is lost.

  8. */

  9. #define container_of(ptr, type, member) ({ \

  10. void *__mptr = (void *)(ptr); \

  11. static_assert(__same_type(*(ptr), ((type *)0)->member) || \

  12. __same_type(*(ptr), void), \

  13. "pointer type mismatch in container_of()"); \

  14. ((type *)(__mptr - offsetof(type, member))); })

此宏就是,给了一个结构体变量的其中成员变量,而获取此结构体变量的地址。ptr是成员变量地址,type是结构体类型,member是成员变量在结构体声明里的名字称谓。

所以说 list_entry 是获取ptr所属的结构体地址。list_first_entry 是获取(ptr)->next 所在结构体的地址,

而list_for_each_entry里面还有宏:

/**

* list_entry_is_head - test if the entry points to the head of the list

* @pos: the type * to cursor

* @head: the head for your list.

* @member: the name of the list_head within the struct.

*/

#define list_entry_is_head(pos, head, member) \

(&pos->member == (head))

这个宏名字取的更敷衍。解释内容说是为了验证是不是list的头指针。 看代码是验证pos这个结构体的成员member地址是不是和head一样。

再看另外一个宏:

/**

* list_next_entry - get the next element in list

* @pos: the type * to cursor

* @member: the name of the list_head within the struct.

*/

#define list_next_entry(pos, member) \

list_entry((pos)->member.next, typeof(*(pos)), member)

解释内容说是获取list的下一个成员指针,看代码是获取(pos)->member.next 所在结构体的地址。

这样整体来看:

#define list_for_each_entry(pos, head, member) \

for (pos = list_first_entry(head, typeof(*pos), member); \ //获取head->next所在结构体地址给pos

!list_entry_is_head(pos, head, member); \//判断pos的member成员地址是否和head一样,如果一样,就跳出循环

pos = list_next_entry(pos, member)) //获取(pos)->member.next 所在结构体的地址

综上所述,这里遍历了一个循环链表,表头是head,但是似乎head没被拿来遍历到?直接从head->next开始的?遍历到再次碰到head的地址就结束了,即表明遍历了一圈了。 member就是链表个成员(链表类型地址)内含的内容地址。这里head为什么是废弃的?

相关推荐
聆风吟201716 分钟前
【数据结构入门手札】数据结构基础:从数据到抽象数据类型
数据结构
AI科技星19 分钟前
自然本源——空间元、氢尺、探针与场方程
数据结构·人工智能·算法·机器学习·计算机视觉
吃着火锅x唱着歌31 分钟前
LeetCode 2874.有序三元组中的最大值II
数据结构·算法·leetcode
小熳芋2 小时前
排序链表- python-非进阶做法
数据结构·算法·链表
zore_c2 小时前
【C语言】数据在内存中的存储(超详解)
c语言·开发语言·数据结构·经验分享·笔记
程序员-周李斌2 小时前
ArrayList 源码深度分析(基于 JDK 8)
java·开发语言·数据结构·算法·list
爪哇部落算法小助手2 小时前
爪哇周赛 Round 3
数据结构·c++·算法
迷途之人不知返3 小时前
二叉树的链式结构
数据结构
不会c嘎嘎3 小时前
【数据结构】红黑树详解:从原理到C++实现
开发语言·数据结构
吃着火锅x唱着歌3 小时前
LeetCode 2364.统计坏数对的数目
数据结构·算法·leetcode