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

相关推荐
橘颂TA16 小时前
【数据结构】解锁数据结构:通往高效编程的密钥
数据结构
LeaderSheepH19 小时前
常见的排序算法
数据结构·算法·排序算法
JasmineX-11 天前
数据结构——静态链表(c语言笔记)
c语言·数据结构·链表
小卡皮巴拉1 天前
【笔试强训】Day1
开发语言·数据结构·c++·算法
༾冬瓜大侠༿1 天前
数据结构:排序
数据结构·算法·排序算法
.YM.Z1 天前
数据结构——链表
数据结构·链表
hn小菜鸡1 天前
LeetCode 2570.合并两个二维数组-求和法
数据结构·算法·leetcode
滋滋不吱吱1 天前
栈的进阶篇
数据结构·算法·leetcode
YQ_ZJH1 天前
Java List列表创建方法大总结
java·开发语言·数据结构·算法·list
Rsingstarzengjx1 天前
【算法】【数学】【质数】质数相关 leetcode 204
数据结构·算法