list_entry/list_for_each_entry/list_for_each_entry_safe
- list_entry
#define list_entry(ptr, type, member) container_of(ptr, type, member)
- ptr type member 分别表示 指针 / 包含指针类型的结构体类型 / 指针对应的成员
- contain_of的原理:已知type的成员member的地址ptr,计算type的首地址
- type的首地址 = ptr – size
container_of
- typeof((type *) 0)->member 获取 member的类型
- __mptr = ptr; 定义一个指针变量__mptr, 并将成员变量ptr的地址赋值给它
- Offsetof(TYPE, MEMBER) 计算成员member这个成员在type类型结构体中偏移
- __mptr – offsetof(type, member) 成员变量的地址减去在结构体中的偏移,就得到了结构体的首地址
- 1 和 2本质上并没有干什么事儿,就是定义了一个中间变量,目的是ptr和member如果传入了错误的类型编译器识别warning
#define container_of(ptr, type, member) ({ \
const typeof(((type *)0)->member) * __mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type, member)); })
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
- list_for_each_entry
#define list_for_each_entry(pos, head, member) \
for (pos = list_first_entry(head, typeof(*pos), member); \
&pos->member != (head); \
pos = list_next_entry(pos, member))
pos head member分别指宿主结构体类型的指针 宿主结构体使用的链表头
宿主结构体中的链表成员
1.pos定位到第一个宿主结构地址
2.判断不等于链表头
3.取下一个宿主结构
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
#define list_next_entry(pos, member) \
list_entry((pos)->member.next, typeof(*(pos)), member)
- list_for_each_entry_safe
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_first_entry(head, typeof(*pos), member), \
n = list_next_entry(pos, member); \
&pos->member != (head); \
pos = n, n = list_next_entry(n, member))
相比list_for_each_entry, list_for_each_entry_safe增加了一个指针n对链表的下一个数据结构进行临时存储,所以在遍历链表的时候如果需要做删除链表的操作,使用list_for_each_entry_safe可以安全的删除,不会影响后续的遍历过程。
该账号已不用···: 这个图是在哪本书上的啊
Acrab_Chogori: 答主写的很好,但是对于一个不懂object的人,您说的其他的也看不懂
ctotalk: 学习
不吃西红柿丶: 很不错分享~ 进步的路上一起努力!期待您的关注哈。
ctotalk: 学习