在之前的文章《深入理解Linux内核之链表 list.h 功能实现原理、接口说明及示例代码》中详细的分析了链表的各种操作,我们经常使用的操作是“初始化”、“ 添加节点”、“遍历”、“删除”,对于链表节点的删除,使用的相对少,而且由于 删除操作的 宏函数 定义的复杂,容易混淆,本文基于此,对 链表的删除清空做下备忘录。
以单向链表结构 为例,用到的宏函数有2个,分别为:
-
/*
-
* Iterate over list of given type safe against removal of list entry.
-
*
-
* @param[in] queue the head for your list.
-
* @param[in] tmp the type * to use as a temp.
-
* @param[in] node the type * to use as a loop cursor.
-
* @param[in] type the type of the struct this is embedded in.
-
* @param[in] member the name of the slist_t within the struct.
-
*/
-
#define slist_for_each_entry_safe(queue, tmp, node, type, member) \
-
for (node = container_of((queue)->next, type, member), \
-
tmp = (queue)->next ? (queue)->next->next :
NULL; \
-
&node->member; \
-
node = container_of(tmp, type, member), tmp = tmp ? tmp->next : tmp)
-
-
/* 节点删除 */
-
static
inline
void slist_del(slist_t *node, slist_t *head)
-
{
-
while (head->next) {
-
if (head->next == node) {
-
head->next = node->next;
-
break;
-
}
-
-
head = head->next;
-
}
-
}
其中 slist_for_each_entry_safe 中包含了 “safe” ,含义是 “安全”, 专用于 链表删除 的 遍历动作。这个函数的参数类型容易有歧义,这里我们做下 解释:
-
/*
-
* Iterate over list of given type safe against removal of list entry.
-
*
-
* @param[in] queue 链表 头 head 指针, 是一个指针
-
* @param[in] tmp struct slist_s * 类型的 临时指针变量
-
* @param[in] node 我们自己的 链表结构 节点 指针,.
-
* @param[in] type 我们自己定义的 链表结构体类型, 必须要包含 struct slist_s list 成员.
-
* @param[in] member 我们自己定义的 链表结构体类型 中的 list 成员
-
*/
-
#define slist_for_each_entry_safe(queue, tmp, node, type, member)
而 slist_del(slist_t *node, slist_t *head) 的参数解释如下:
-
/*
-
* Iterate over list of given type safe against removal of list entry.
-
*
-
* @param[in] node struct slist_s * 类型的 节点变量,是一个指针
-
* @param[in] head 链表 头 head 指针, 是一个指针
-
*/
-
-
static
inline
void slist_del(slist_t *node, slist_t *head)
删除并释放 所有链表节点的 程序案例:
-
/* 自定义的 链表结构体*/
-
typedef
struct{
-
int
id;
-
int a;
-
int b;
-
struct slist_s list;
-
} usr_list_info_t;
-
-
-
/*--------------- 删除整个链表的伪操作 ---------------*/
-
struct slist_s *head = get_usr_list_head();
-
struct slist_s *tmp =
NULL;
-
usr_list_info_t *node =
NULL;
-
-
slist_for_each_entry_safe(head, tmp, node, usr_list_info_t, list){
-
slist_del(&(node->list), head);
-
free(node);
-
}
如果想删除某一个节点,也是上面的套路,只不过在遍历所有的节点同时,判断当前节点是否是我们想要删除的节点,如果是,则删除,不是则接着遍历。
转载:https://blog.csdn.net/u012351051/article/details/103736625
查看评论