当前位置: 首页 > 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 WAY1LIST_HEAD(TEST);
#elsetest TEST;INIT_LIST_HEAD(&TEST.L);
#endifint 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 WAY1list_add_tail(p, &TEST);
#elselist_add_tail(p, &TEST.L);
#endifprintf("p->a:%d, p->b:%d, p->c:%d\n", p->a, p->b, p->c);}}struct list_head *pos = NULL;
#ifdef WAY1list_for_each(pos, &TEST)
#elselist_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 WAY1LIST_HEAD(TEST);
#elsetest TEST;INIT_LIST_HEAD(&TEST.L);
#endifint 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 WAY1list_add_tail(&p->L, &TEST);//函数,参数都是指针
#elselist_add_tail(&p->L, &TEST.L);
#endifprintf("p->a:%d, p->b:%d, p->c:%d\n", p->a, p->b, p->c);}}struct list_head *pos = NULL;
#ifdef WAY1list_for_each(pos, &TEST)//pos就是list_head类型的遍历的迭代器
#elselist_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 WAY1list_for_each(pos, &TEST)
#elselist_for_each(pos, &TEST.L)
#endif{test * p3 = list_entry(pos, test, L);list_del(pos);free(p3);}return 0;
}

相关文章:

  • TPL0401B使用教程
  • springboot+vue的养老院管理系统
  • 【机器学习】让大模型变得更聪明
  • C#根据数据量自动排版标签的样例
  • 【CPP】栈简介及简化模拟实现
  • C语言学习笔记之结构体(一)
  • Android 车载 Audio 中 有关系统按键无声的问题排查小结
  • qi5uxeel算法分析流程记录libmsec.so
  • 14.微信小程序之地理定位功能
  • OSG学习记录
  • uniapp条件编译
  • object对象列表使用sorted函数按照对象的某个字段排序
  • 运维开发.Kubernetes探针与应用
  • 详细介绍运算符重载函数,清晰明了
  • 使用matplotlib绘制折线条形复合图
  • [译] React v16.8: 含有Hooks的版本
  • echarts的各种常用效果展示
  • ES6语法详解(一)
  • Joomla 2.x, 3.x useful code cheatsheet
  • js面向对象
  • Meteor的表单提交:Form
  • Python中eval与exec的使用及区别
  • Redis的resp协议
  • Shadow DOM 内部构造及如何构建独立组件
  • Spring-boot 启动时碰到的错误
  • vue--为什么data属性必须是一个函数
  • 服务器从安装到部署全过程(二)
  • 猴子数据域名防封接口降低小说被封的风险
  • 前端相关框架总和
  • 使用Maven插件构建SpringBoot项目,生成Docker镜像push到DockerHub上
  • 数组的操作
  • 微信开源mars源码分析1—上层samples分析
  • #NOIP 2014# day.2 T2 寻找道路
  • (1)(1.19) TeraRanger One/EVO测距仪
  • (10)ATF MMU转换表
  • (BFS)hdoj2377-Bus Pass
  • (delphi11最新学习资料) Object Pascal 学习笔记---第14章泛型第2节(泛型类的类构造函数)
  • (done) ROC曲线 和 AUC值 分别是什么?
  • (Python) SOAP Web Service (HTTP POST)
  • (vue)页面文件上传获取:action地址
  • (ZT) 理解系统底层的概念是多么重要(by趋势科技邹飞)
  • (附源码)SSM环卫人员管理平台 计算机毕设36412
  • (附源码)ssm基于jsp高校选课系统 毕业设计 291627
  • (一)utf8mb4_general_ci 和 utf8mb4_unicode_ci 适用排序和比较规则场景
  • ****** 二十三 ******、软设笔记【数据库】-数据操作-常用关系操作、关系运算
  • .bat批处理(六):替换字符串中匹配的子串
  • .net 程序 换成 java,NET程序员如何转行为J2EE之java基础上(9)
  • .NET 中让 Task 支持带超时的异步等待
  • .net 重复调用webservice_Java RMI 远程调用详解,优劣势说明
  • .net用HTML开发怎么调试,如何使用ASP.NET MVC在调试中查看控制器生成的html?
  • .net之微信企业号开发(一) 所使用的环境与工具以及准备工作
  • @德人合科技——天锐绿盾 | 图纸加密软件有哪些功能呢?
  • [.net]官方水晶报表的使用以演示下载
  • [AutoSar NVM] 存储架构
  • [BZOJ] 1001: [BeiJing2006]狼抓兔子