linux双向列表list_head使用方法

list_head是linux中使用非常广泛的双向列表,list_head源代码所在位置为include/linux/list.h。

以下为测试代码:

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

#define LIST_POISON1  ((void *) 0x00100100)
#define LIST_POISON2  ((void *) 0x00200200)

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

static inline void INIT_LIST_HEAD(struct list_head *list)
{
	list->next = list;
	list->prev = list;
}

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(struct list_head *new, struct list_head *head)
{
	__list_add(new, head, head->next);
}

static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
	__list_add(new, head->prev, head);
}

static inline int list_empty(const struct list_head *head)
{
	return head->next == head;
}

static inline void __list_del(struct list_head * prev, struct list_head * next)
{
	next->prev = prev;
	prev->next = next;
}

static inline void list_del(struct list_head *entry)
{
	__list_del(entry->prev, entry->next);
	entry->next = LIST_POISON1;
	entry->prev = LIST_POISON2;
}

#define prefetch(x) __builtin_prefetch(x)

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

struct Student{
    int id;
    struct list_head list_head;
};

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

#define container_of(ptr, type, member) ({          \
    const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
    (type *)( (char *)__mptr - offsetof(type,member) );})

struct Student* find_student(int id, struct list_head *list_head)
{
    struct list_head *cur;
    list_for_each(cur, list_head) {
		struct Student *ptr_stu = container_of(cur, struct Student, list_head);
        
        if (id == ptr_stu->id)
        {
            return ptr_stu;
        }

	}

    return NULL;
}

int main()
{
    struct list_head list_head;
    INIT_LIST_HEAD(&list_head);

    for (int  i = 10; i <= 100; i+=10)
    {
        struct Student *ptr_stu = malloc(sizeof(struct Student));
        ptr_stu->id = i;

        if (i == 40 || i == 60)
        {
            // 添加到尾部
            list_add_tail(&ptr_stu->list_head, &list_head);
        }
        else
        {
            // 添加到头部
            list_add(&ptr_stu->list_head, &list_head);
        }
    }

    if (list_empty(&list_head))
    {
        printf("list is empty\n");
        return 0;
    }
    
    // 打印
    struct list_head *cur;
    list_for_each(cur, &list_head) {
		struct Student *ptr_stu = container_of(cur, struct Student, list_head);
        printf("id = %d\n", ptr_stu->id);

	}

    // 删除id为50的对象
    struct Student *ptr_stu = find_student(50, &list_head);
    if (NULL != ptr_stu)
    {
        list_del(&ptr_stu->list_head);

        free(ptr_stu);
        ptr_stu = NULL;
    }

    printf("\nprint after del\n");
    list_for_each(cur, &list_head) {
		struct Student *ptr_stu = container_of(cur, struct Student, list_head);
        printf("id = %d\n", ptr_stu->id);

	}

    return 0;
}

运行结果如下:

id = 100
id = 90
id = 80
id = 70
id = 50
id = 30
id = 20
id = 10
id = 40
id = 60

print after del
id = 100
id = 90
id = 80
id = 70
id = 30
id = 20
id = 10
id = 40
id = 60

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值