当前位置: 首页 > news >正文

Linux-struct list_head的快速使用

Linux-struct list_head的快速使用

struct list_head {
	struct list_head *next, *prev;
};

初始化

LIST_HEAD_INIT

#define LIST_HEAD_INIT(name) { &(name), &(name) }//结合LIST_HEAD看,直接next,prev赋值
#define LIST_HEAD(name)
struct list_head name = LIST_HEAD_INIT(name)//定义并初始化链表头结点
例如:LIST_HEAD(test_head);

INIT_LIST_HEAD

#define INIT_LIST_HEAD(ptr) do { \ //初始化已经定义了的链表头结点
(ptr)->next = (ptr); (ptr)->prev = (ptr);
} while (0)
例如:MSG_Q_ID QId[MAX_Q]; INIT_LIST_HEAD(&QId[msgKey].MsgQ_List);

static inline void prefetch(const void *x) {;} //prefetch预读取  目前实现为空,或许是留下接口,方便实现真正的预读取逻辑

#define list_for_each(pos, head) \
	for (pos = (head)->next, prefetch(pos->next); pos != (head); \
        	pos = pos->next, prefetch(pos->next))

==========================================================
static __inline__ void __list_add(struct list_head * new,
	struct list_head * prev,
	struct list_head * next)
{
	next->prev = new;
	new->next = next;
	new->prev = prev;
	prev->next = new;
}
static __inline__ void list_add_tail(struct list_head *new, struct list_head *head)
{
	__list_add(new, head->prev, head);//尾部结点:next是头部,prev是头部的prev
}
==========================================================
#define list_entry(ptr, type, member) \ //获取ptr->member
	((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
==========================================================
#define list_for_each(pos, head) \ //遍历head链表
	for (pos = (head)->next, prefetch(pos->next); pos != (head); \
        	pos = pos->next, prefetch(pos->next))
#define list_for_each_safe(pos, n, head) \ //用了一个中间参数,safe?
	for (pos = (head)->next, n = pos->next; pos != (head); \
		pos = n, n = pos->next)
==========================================================
#define list_for_each_prev(pos, head) \ //前向遍历
	for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \
        	pos = pos->prev, prefetch(pos->prev))
==========================================================

实例

LIST_HEAD和INIT_LIST_HEAD的区别:
1. 主要是初始化部分,变量是否已经定义
LIST_HEAD => struct list_head
INIT_LIST_HEAD => struct XXX
2. 需要注意的是:以下代码运行成功的前提是:第一个成员变量类型必须是list_head

#include "list.h"
#include <stdio.h>
#include <stdlib.h>
#define WAY1
#undef WAY1
typedef struct test
{
    struct list_head L;
    int a;
    int b;
    int c;
} test;
int main()
{
#ifdef WAY1
    LIST_HEAD(TEST);
#else
    test TEST;
    INIT_LIST_HEAD(&TEST.L);
#endif
    int i;
    for (i = 1; i < 10; i++)
    {
        test *p = NULL;
        p = malloc(sizeof(test));
        if (p)
        {
            p->a = i;
            p->b = i;
            p->c = i;
#ifdef WAY1
            list_add_tail(p, &TEST);
#else
            list_add_tail(p, &TEST.L);
#endif
            printf("p->a:%d, p->b:%d, p->c:%d\n", p->a, p->b, p->c);
        }
    }
    struct list_head *pos = NULL;
#ifdef WAY1
    list_for_each(pos, &TEST)
#else
    list_for_each(pos, &TEST.L)
#endif
    {
        test *p2 = list_entry(pos, test, L);
        printf("p2->a:%d, p2->b:%d, p2->c:%d\n", p2->a, p2->b, p2->c);
    }
    return 0;
}

如果想设置第一个成员变量不是struct list_head类型,则如下修改:
区别就在于list_add_tail加入的结点需要指定成员。

#include "list.h"
#include <stdio.h>
#include <stdlib.h>
#define WAY1
//#undef WAY1
typedef struct test
{    
    int a;
    int b;
    struct list_head L;
    int c;
} test;
int main()
{
#ifdef WAY1
    LIST_HEAD(TEST);
#else
    test TEST;
    INIT_LIST_HEAD(&TEST.L);
#endif
    int i;
    for (i = 1; i < 10; i++)
    {
        test *p = NULL;
        p = malloc(sizeof(test));
        if (p)
        {
            p->a = i;
            p->b = i;
            p->c = i;
#ifdef WAY1
            list_add_tail(&p->L, &TEST);//函数,参数都是指针
#else
            list_add_tail(&p->L, &TEST.L);
#endif
            printf("p->a:%d, p->b:%d, p->c:%d\n", p->a, p->b, p->c);
        }
    }
    struct list_head *pos = NULL;
#ifdef WAY1
    list_for_each(pos, &TEST)//pos就是list_head类型的遍历的迭代器
#else
    list_for_each(pos, &TEST.L)
#endif
    {
        test *p2 = list_entry(pos, test, L);//pos指向test类型的L成员变量
        printf("p2->a:%d, p2->b:%d, p2->c:%d\n", p2->a, p2->b, p2->c);
    }

#ifdef WAY1
    list_for_each(pos, &TEST)
#else
    list_for_each(pos, &TEST.L)
#endif
    {
        test * p3 = list_entry(pos, test, L);
        list_del(pos);
        free(p3);
    }
    return 0;
}

相关文章:

  • 流媒体内网穿透/组网/视频协议转换EasyNTS上云网关如何更改密码?
  • 阿里云部署nodejs
  • 2024蓝桥杯国赛C++研究生组游记+个人题解
  • allure测试报告用例数和 pytest执行用例数不相同问题
  • 【Java】面向对象的三大特征:封装、继承、多态
  • 最低要求条件下的商环定义
  • 【2.文件和目录相关(下)】
  • 网络运维的重要性
  • # Java 基础面试300题 (51-80)
  • 互联网政务应用安全管理规定:使用安全连接方式访问
  • [AI OpenAI] 通过隐蔽影响行动破坏AI的欺骗性使用
  • php TP8 阿里云短信服务SDKV 2.0(跳大坑)
  • 远程连接服务器
  • Kotlin 泛型
  • cocos creator 3.x实现手机虚拟操作杆
  • Python 关于字符串格式化
  • 【Linux】将U盘中的程序更新到开发板中 shell 脚本
  • VRTK4教程 一:资源导入、Unity设置、连接头盔
  • SO3控制器原理与实现(对飞行器的控制实践)
  • 算法(十一)贪婪算法
  • 跨越时空的“精神返乡”,叶灵凤藏书票捐赠上海文学馆
  • 碧桂园:砸锅卖铁保交房、持续推进保主体,尽快让公司恢复正常经营
  • 习近平向中国人民解放军仪仗队致意
  • 中国以优化营商环境为支点,为全球企业提供可预期市场环境
  • 复旦发文缅怀文科杰出教授裘锡圭:曾提出治学需具备三种精神
  • 人民日报评“组团退演出服”:市场经济诚信原则需全社会维护