当前位置:   article > 正文

Linux中的list使用_linux list

linux list

1:使用说明

在linux下有一种常用的链表结构。当你需要很多相同结构体,并想把它们连接在一起。方便你增减或者逐个访问的时候,可以用这种结构。当然你也可以直接用链表指针,那么你就必须自己写,初始化链表,添加和删除,循环访问等函数。如果直接用list,就是直接把struct list_head放在你的结构体里。然后包含一个头文件list.h。就可以直接使用现成的链表操作的各种函数(创建, 增加, 删除和遍历)。

list.h下载

2:常用函数

2.1 list_head

struct list_head {
    struct list_head *next, *prev;
};
  • 1
  • 2
  • 3

list的结构体,里面只有两个指针。一个向前指,一个向后指

2.2:LIST_HEAD_INIT

#define LIST_HEAD_INIT(name) { &(name), &(name) }
  • 1

初始化这个链表指向自己,相当于下面的图
在这里插入图片描述

2.3:list_add

/*
 * Insert a new entry between two known consecutive entries.
 *
 * This is only for internal list manipulation where we know
 * the prev/next entries already!
 */
static inline void __list_add(struct list_head *new,
                  struct list_head *prev,
                  struct list_head *next)
{
    if (!__list_add_valid(new, prev, next))
        return;

    next->prev = new;
    new->next = next;
    new->prev = prev;
    WRITE_ONCE(prev->next, new);//等价与 prev->next = new
}

/**
 * list_add - add a new entry
 * @new: new entry to be added
 * @head: list head to add it after
 *
 * Insert a new entry after the specified head.
 * This is good for implementing stacks.
 */
static inline void list_add(struct list_head *new, struct list_head *head)
{
    __list_add(new, head, head->next);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

把新链表new,添加在head之前,相当于下图,把新节点往前放。

在这里插入图片描述

2.4 list_del

/**
 * list_del - deletes entry from list.
 * @entry: the element to delete from the list.
 * Note: list_empty on entry does not return true after this, the entry is in an undefined state.
 */
static inline void list_del(struct list_head *entry)
{
    __list_del(entry->prev, entry->next);
    entry->next = (void *) 0;
    entry->prev = (void *) 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

删除链表中的一个节点

2.4:list_for_each

/**
 * list_for_each    -   iterate over a list
 * @pos:    the &struct list_head to use as a loop cursor.
 * @head:   the head for your list.
 */
#define list_for_each(pos, head) \
    for (pos = (head)->next; pos != (head); pos = pos->next)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

这个宏, 的作用就是从head开始的第一个函数开始, 遍历这个链表, 用for语句

2.5 list_entry

/**
 * list_entry - get the struct for this entry
 * @ptr:    the &struct list_head pointer.
 * @type:   the type of the struct this is embedded in.
 * @member: the name of the list_head within the struct.
 */
#define list_entry(ptr, type, member) \
    container_of(ptr, type, member)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
#ifndef container_of
/**
 * container_of - cast a member of a structure out to the containing structure
 * @ptr:    the pointer to the member.
 * @type:   the type of the container struct this is embedded in.
 * @member: the name of the member within the struct.
 *
 */
#define container_of(ptr, type, member) ({          \
    const typeof(((type *)0)->member) * __mptr = (ptr); \
    (type *)((char *)__mptr - offsetof(type, member)); })
#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

这个的作用就是从ptr所指的type的类型,寻找member的这个变量。
大概意思就是,通过ptr的位置找到prt所在结构体的位置。这个结构体的类型是type

typedef struct stud
{   
    struct list_head list;
    char name[MAX_NAME_LEN];
    char stu_number[MAX_ID_LEN];
}num_n_stu;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

例如这个结构体。通过list的位置,确定stud的位置。
如果想了解细节:请参考这里

3:示例

/*************************************************************************
    > File Name: list.c
    > Author: kayshi
    > Mail: kayshi2019@qq.com
    > Created Time: Fri 30 Oct 2020 11:28:54 AM CST
 ************************************************************************/

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

#include "list.h"

#define MAX_NAME_LEN 32
#define MAX_ID_LEN 10

typedef struct stud
{   
    struct list_head list;
    char name[MAX_NAME_LEN];
    char stu_number[MAX_ID_LEN];
}num_n_stu;

typedef struct stud_1
{
    struct list_head list;
    char name[MAX_NAME_LEN];
    char stu_number[MAX_ID_LEN];
    char id; 
}num_n_stu1;

int main(void)
{
    struct list_head head;
    num_n_stu stu_1;
    num_n_stu stu_2;
    num_n_stu1 stu_x;
    num_n_stu *entry;

    struct list_head *p; 
    INIT_LIST_HEAD(&head);
    strcpy(stu_1.name, "lisi");
    strcpy(stu_1.stu_number, "10000000");
        strcpy(stu_2.name, "kay");
    strcpy(stu_2.stu_number, "10000001");
    strcpy(stu_x.name, "yan");
    strcpy(stu_x.stu_number, "10000002");

    list_add(&stu_1.list, &head);
    list_add(&stu_2.list, &head);
    list_add(&stu_x.list, &head);
    //list_del(&stu_2.list);
    list_for_each(p, &head)
    {
        entry= list_entry(p, struct stud, list);
        printf("name:%s\n", entry->name);
        printf("stu_number:%s\n", entry->stu_number);
    }
    list_del(&stu_1.list);
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60

结果

kayshi@ubuntu:~/code/list$ ./a.out 
name:yan
stu_number:10000002
name:kay
stu_number:10000001
name:lisi
stu_number:10000000
kayshi@ubuntu:~/code/list$ 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

note:你会发现遍历打印的顺序和加入的顺序相反,这也说明了加入是向head前面加的

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/128113
推荐阅读
相关标签
  

闽ICP备14008679号