list 移植与基本使用

Linux中List.h文件的分析和应用 本文介绍Linux中List.h文件,此文件中用双向链表实现了多种数据结构,比如队列,堆栈等,短小精湛,值得借鉴。此文件中还有哈希表的应用。 阅读详情

1. 概述:
该demo主要实现list链表的基本使用, 增删查改
list.h 移植 linux-4.9.37\include\linux\list.h

2. 测试:
在这里插入图片描述

/*
linux-4.9.37\include\linux\list.h
*/

/*
static inline
内联函数, 节省函数调用所需的栈空间, 执行效率高
*/

/*
双链表结构, 是一个双向循环链表, 或者说是双向环形链表
*/
struct list_head {
   
   
    struct list_head *next, *prev;
};

/*
初始化已经定义过的变量
*/
#define LIST_HEAD_INIT(name) {
     
      &(name), &(name) }

/*
定义struct list_head类型头指针, 并且初始化
*/
#define LIST_HEAD(name) \
    struct list_head name = LIST_HEAD_INIT(name)

/*
初始化链表头指针head, 将prev和next元素都指向list本身
*/
static inline void INIT_LIST_HEAD(struct list_head *list);

/*
添加new节点到head之后, head是链表头
*/
static inline void list_add(struct list_head *new, struct list_head *head);

/*
添加new节点到head之前, head是链表头
*/
static inline void list_add_tail(struct list_head *new, struct list_head *head);

/*
删除链表节点entry
*/
static inline void list_del(struct list_head *entry);

/*
判断链表是否为空, 也可以判断链表中任意一个节点是否为空
*/
static inline int list_empty(const struct list_head *head);

/*
获取链表中某个节点的地址
*/
#define list_entry(ptr, type, member) \
    container_of(ptr, type, member)

/*
获取链表中第一个节点的地址
*/
#define list_first_entry(ptr, type, member) \
    list_entry((ptr)->next, type, member)

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

/*
*/
#define list_for_each_safe(pos, n, head) \
    for (pos = (head)->next, n = pos->next; pos != (head); \
        pos = n, n = pos->next)

/*
遍历链表
*/
#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))

/*
list_for_each_entry的安全版, 当遍历过程中涉及到删除节点的时候, 使用该宏函数
*/
#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))

/*
反向遍历链表
*/
#define list_for_each_entry_reverse(pos, head, member)            \
    for (pos = list_last_entry(head, typeof(*pos), member);        \
         &pos->member != (head);                     \
         pos = list_prev_entry(pos, member))
/*
    From : https://github.com/paiminlin/PM
    From : https://blog.csdn.net/lpaim/article/details/114681720
    Author : PaiMin.lin
    Date : 2022.8.21
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#define LPM
#include "list.h"

#ifdef __cplusplus
extern "C"{
   
   
#endif

#define Demolist_MAIN_DEBUG
#ifdef Demolist_MAIN_DEBUG

#define MAX_BUF         64

struct file_name_info
{
   
   
    int index;
    char name[MAX_BUF];
    struct list_head list;
};

int main(int argc, char *argv[]) {
   
   

    int i = 0;
    struct file_name_info * pfileinfo = NULL;
    struct file_name_info * ptmpfileinfo = NULL;

    LIST_HEAD(filehead);

    printf("*** insert the file list ***************************\n");
    pfileinfo = NULL;
    for(i = 0; i < 5; i++){
   
   
        pfileinfo = (struct file_name_info *)malloc(sizeof(struct file_name_info));
        pfileinfo->index = i + 1;
        snprintf(pfileinfo->name, sizeof(pfileinfo->name), "%d.txt", pfileinfo->index);
        list_add(&pfileinfo->list, &filehead);
    }

    printf("*** printf the file list ***************************\n");
    pfileinfo = NULL;
    list_for_each_entry(pfileinfo, &filehead, list){
   
   
        printf("file index : %d name : %s\n", pfileinfo->index, pfileinfo->name);
    }

    printf("*** change the 3 node ******************************\n");
    pfileinfo = NULL;
    list_for_each_entry(pfileinfo, &filehead, list){
   
   
        if(pfileinfo->index == 3){
   
   
            snprintf(pfileinfo->name, sizeof(pfileinfo->name), "%s.txt", "change");
            break;
        }
    }

    printf("*** printf the file list ***************************\n");
    pfileinfo = NULL;
    list_for_each_entry(pfileinfo, &filehead, list){
   
   
        printf("file index : %d name : %s\n", pfileinfo->index, pfileinfo->name);
    }

    printf("*** delete the 3 node ******************************\n");
    pfileinfo = NULL;
    ptmpfileinfo = NULL;
    list_for_each_entry_safe(pfileinfo, ptmpfileinfo, &filehead, list){
   
   
        if(pfileinfo->index == 3){
   
   
            list_del(&(pfileinfo->list));
            free(pfileinfo);
            break;
        }
    }

    printf("*** printf the file list ***************************\n");
    pfileinfo = NULL;
    list_for_each_entry(pfileinfo, &filehead, list){
   
   
        printf("file index : %d name : %s\n", pfileinfo->index, pfileinfo->name
Linux内核链表(list)移植到任意平台 linux内核链表在文件中,内核中实现的链表比较简洁,实用性很强,因此想把它单独移植出来使用。内核中的代码只能使用编译器编译,编译器编译是会报错的,主要是因为这个宏是gnuc特有的扩展,stdc中没有此扩展。本篇文章就是来解决这个问题的,移植得到一个在stdc下运行的list,方便其他平台使用。 修改并添加了以下宏,改完后可以在stdc下编译: 1、和。 2、,去除了的使用。 -3、删除所有使用的定义,将以下代码删除: 至此,移植完成。 四、使用方法 4.1、初始化链表 或 阅读详情

相关推荐

SharePoint 2013 在不同的环境中(开发环境,测试环境,生产环境)移植由SharePoint designer 2013 设计的List Workflow

本文讲述SharePoint 2013如何在不同的环境之间(开发环境,测试环境,生产环境)移植由SharePoint designer 2013 设计的List Workflow。 在SharePoint 2010和2007 中,如果针对某个List 使用 SharePoint designer设计一个Workflow,通常我们有 三个环境(开发环境,测试环境,生产环境),但是我没办法把work

farawayplace613的专栏 3788

c语言内核链表list.h的解释及应用_c笔记

一个简单的学生管理系统。

fudra的博客 864

农业AI避坑指南:用YOLO11做叶片病害检测时遇到的5个典型问题

本文分享了使用YOLO11模型进行农业叶片病害检测时常见的五个典型问题及解决方案。针对田间多变光照、病害样本不均衡、标注歧义、背景干扰和边缘部署等挑战,提供了包括场景自适应数据增强、解耦训练、软标签鲁棒损失函数、困难负样本构建以及模型轻量化部署在内的实战经验,旨在帮助开发者提升农业AI项目的落地效果。

ujm56789012的博客 186

【数据结构】list.h 常用函数实现详解

本文介绍了 list.h 的函数实现,对如何使用 list.h 有一定帮助。

wkd_007的博客 2350

【数据结构】list.h 详细使用教程 -- 附带例子代码

介绍list.h 的详细用法,并给出例子代码

wkd_007的博客 1977

linux list.h 移植

Linux内核中List链表的实现,对于想进阶的程序员来说,无疑是一个很好的学习机会。内核实现了一个功能十分强大的链表,而且是开源的,用在其他需要的地方岂不是很省事。 一、看List实现前,先补充typeof的知识,方便阅读。 typeof(int *) p1, p2; /* Declares two int pointers p1, p2 */ int *...

305

LibCSTL开发手记:Linux Kernel list 移植优化

移植后我们只需要将list_node定义在你自己的结构体中即可。为了可读性和操作简化,请把list_node定义在结构体头部,虽然对于list来说你不把它定义在头部也没有关系。这是Linux内核中很常用的一个宏定义,配合offsetof可以轻松根据结构体成员计算出结构体首地址,内核通用链表实现依赖于这个红。我么先来看offsetofsize_t0->这个宏用来获取结构体成员的偏移,通过将结构体首地址定义为 0 ,从而获取结构体成员相对于 0 的偏移, 也就是相对于结构体首地址的偏移。再来看。

2301_79077042的博客 505

Linux内核数据结构移植list和rbtree)

简介list 介绍修改部分list.h 对外的接口使用示例 - 测试 list.h 中所有的list操作rbtree 介绍修改部分rbtree.h 对外接口使用示例 简介 主要移植了内核中的 list,rbtree。使得这2个数据结构在用户态程序中也能使用。同时用 cpputest 对移植后的代码进行了测试。(测试代码其实也是使用这2个数据结构的方法) 内核代码的如下文件:(内核版本 v3.2 ...

Stay Hungry, Stay Foolish 1106

Linux内核中的通用链表list.h在windows下的移植实现

在windows的通用开发平台上,有MFC或者STL的支持,很少自己去编写一个链表list程序。现在把Linux下的list.h取出来,在Windows平台上实现: 我这里用的是Linux2.4版本的,2.6版本的其实都一样,下面是修改后的list.h源文件,注意几点:① 注释掉了和Linux相关的字眼,如第三行等等,添加了prefetch(w)两个函数的实现;② 因为是在C语言下实现(

dijkstar的专栏 5681

Kernel数据结构移植list和rbtree)

Kernel数据结构移植list和rbtree) 主要移植了内核中的 list,rbtree。使得这2个数据结构在用户态程序中也能使用。同时用 cpputest 对移植后的代码进行了测试。(测试代码其实也是使用这2个数据结构的方法) 内核代码的如下文件:(内核版本 v3.2 debian 7.5源码)include/linux/list.h  (删除了 hlist 相关内容)includ

Augusdi的专栏 1601

Linux 中list移植使用

从linux源码中抠出关于list的相关代码  #ifndef _LINUX_LIST_H #define _LINUX_LIST_H #ifdef __cplusplus extern "C"{ #endif struct list_head { struct list_head *next, *prev; }; /** *Simple doubly linked list ...

shy19910509的专栏 729

linux——list.h

*linux中的头文件list.h 在Linux的源码中有一个自己为建立链表而写的链表头文件,以后可以直接调用里面的函数来使用链表。 list.h在linux中的路径为/usr/src/kernels/include/linux。不同的版本可能不一样。 list.h中有两个宏定义:#define LIST_HEAD_INIT(name) {&(name),&(name)} #define LI

sinat_34467747的博客 7511

深入理解Linux内核之链表 list.h 功能实现原理、接口说明及示例代码

目录 一、双向链表接口函数及相关宏定义分析 0、list_head 结构体 1、offsetof(TYPE, MEMBER) 宏 2、ontainer_of(ptr, type, member) 宏 3、LIST_HEAD_INIT 宏 4、LIST_HEAD 宏 5、INIT_LIST_HEAD 函数 6、LIST_HEAD 和INIT_LIST_HEAD 的区别 7、lis...

猪哥的专栏 7603

C语言---list.h宏解读

C语言—宏解读 这个宏定义,主要就返回一个结构体成员的指针 环境:mac + gcc编译器 + vscode代码编辑器 #define list_entry(ptr, type, member) \ ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member))) 先来一段代码说明怎么使用和作用 ...

小豹Miss鲍的博客 4161

Linux 中list.h使用实例和坑

list.h是Linux内核中,为了提供统一的链表操作,减少结构体的额外开支提供的链表操作。list.h中定义的链表了一个双向循环链表,和一个哈希表。内含实际例子 ​

monkeyzh123的专栏 3228

数据结构-链表list.h 使用操作

读者可自己画个读,就不难发现 list_add_tail 宏所实现的是一个类头插法,它是将节点插入在头节点的前面,但是头节点的位置不会变,也就是以我们一开始定义的头节点为头,新来的节点始终插入在这个头节点的前面,所以可以看到__list_add 中的操作就是将新节点插入在头节点和头节点前面元素之间。在对链表进行操作之前,首先我们需要为链表指定好链表头,以方便管理,后面的操作接口中的参数很多也是要和这个链表头有关联,在操作之前,要先定义一个。是返回头节点下一个节点的节点地址,因为头节点就是一个。

jiu_yue_ya的博客 633

list.h使用说明

1     位置 2     数据结构 3     接口 3.1  offsetof 3.2  container_of 3.LIST_HEAD_INIT 3.LIST_HEAD 3.5  INIT_LIST_HEAD 3.6 _list_add 3.list_add 3.list_add_tail 3.

lmjjw的专栏 1万+

内核链表 list.h

记录一下整理的关于内核链表相关函数内容 一、双指针双向循环链表(list) 1. 基本原理 struct list_head { struct list_head* pPre; struct list_head* pNext; }; typedef struct _STU { char cSex; char szAddress[128]; int iNumber; int iFlag; struct list_head mylist; }STU;

qq_43001551的博客 302

mysql数据库中使用存储过程带来的好处和示例(存储过程的概念、定义、作用等详解)

MySQL的存储过程(Stored Procedure)是一组SQL语句集合。用户通过指定的存储过程名和参数来调用并执行它。存储过程可以在数据库中预编译并存储,这样它们可以被多次调用而无需重新编写或解析SQL语句。 存储过程将复杂的SQL逻辑封装在一个可重用的单元中。多次调用存储过程,而不需要重复编写相同的SQL代码。- 通过封装,可以隐藏复杂的SQL逻辑,只向用户或应用程序提供简单的接口。MySQL的存储过程和编程语言中的函数的原理和目标是一致的:封装可重用的代码逻辑并提高代码的可维护性和可重用性。

weixin_70208651的博客 1691

three.min.js和webvr-polyfill.min.js

webvr开发所需的两个前端js插件

上一篇: Linux 定时器 基本使用
下一篇: json 配置文件操作
无聊人lpm
博客等级 码龄9年 9粉丝 31原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值