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为什么是废弃的?

相关推荐
菜鸟233号10 小时前
力扣669 修剪二叉搜索树 java实现
java·数据结构·算法·leetcode
jingfeng51413 小时前
哈希表的概念+实现
数据结构·哈希算法·散列表
ホロHoro13 小时前
数据结构非线性部分(1)
java·数据结构·算法
沉下去,苦磨练!14 小时前
实现二维数组反转
java·数据结构·算法
玖剹14 小时前
哈希表相关题目
数据结构·c++·算法·leetcode·哈希算法·散列表
红豆诗人14 小时前
数据结构初阶知识--单链表
c语言·数据结构
L_090714 小时前
【C++】高阶数据结构 -- 二叉搜索树(BST)
数据结构·c++
仰泳的熊猫15 小时前
1150 Travelling Salesman Problem
数据结构·c++·算法·pat考试
lixzest16 小时前
C++中经常用的头文件介绍
数据结构·c++·算法
一起养小猫16 小时前
《Java数据结构与算法》第四篇(四):二叉树的高级操作查找与删除实现详解
java·开发语言·数据结构·算法