数据结构-内核的双向循环链表-简单实现

Posted muzihuan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构-内核的双向循环链表-简单实现相关的知识,希望对你有一定的参考价值。

list.h

技术分享
#ifndef LIST_H__
#define LIST_H__

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

#define LIST_HEAD_INIT(name)        { &(name), &(name) }
#define LIST_HEAD(name)             struct list_head name = LIST_HEAD_INIT(name)
#define __list_for_each(pos, head)  for (pos = (head)->next; pos != (head); pos = pos->next)


/*
  const typeof( ((type *)0)->member ) *__mptr = (ptr);
     --->定义类型为(typeof获取member的类型)的指针* __mptr,并将ptr的值(实际地址)赋值给__mptr;
  (type *)( (char *)__mptr - offsetof(type,member) );
     --->用member实际的地址 - 偏移地址 就是数据结构实例的地址;
*/
#define container_of(ptr, type, member) ({                      const typeof( ((type *)0)->member ) *__mptr = (ptr);                (type *)( (char *)__mptr - offsetof(type,member) );})


//offsetof宏:member成员到type结构实例类型的高度:
//假设type结构的实例的地址是0 强转成char(*),再找到->member,就找到member距离结构体实例的偏移
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)


//ptr->cur:指向成员member的地址
//member:成员在结构实例内部的名称,如果为数组,需要下标
//type->struct score_st需要返回的结构实例类型
#define list_entry(ptr, type, member)  container_of(ptr, type, member)


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);
}


#endif
View Code

main.c

技术分享
#include <stdio.h>
#include <stdlib.h>
#include "list.h"

#define NAMESIZE    32
//定义结构体
struct score_st
{
    int id ;
    char name[NAMESIZE] ;
    int math ;
    int chinese ;
    struct list_head node ;//*PREV *NEXT
};
//打印函数
static void print_s(struct score_st *d) 
{
    printf("%d %s %d %d \n",d->id ,d->name , d->math , d->chinese);
}



int main()
{
    int i ; 
    struct score_st *datap ;
    struct list_head *cur ;
    //1.创建头
    LIST_HEAD(head);
    //2.头部插入8个节点并赋值
    for(i = 0 ; i < 8 ; i++)
    {   
        datap = malloc(sizeof(*datap));
        if(datap == NULL)
            exit(1);
        datap->id = i ; 
        snprintf(datap->name,NAMESIZE ,"stu%d",i);
        datap->math = rand()%100;
        datap->chinese = rand()%100;
        list_add(&datap->node,&head);
    }   
    //3.打印链表
    __list_for_each(cur, &head)
    {   
        datap = list_entry(cur,struct score_st,node);
        print_s(datap);
    }   
    //4.查找链表内部id为5的节点
    __list_for_each(cur, &head)
    {   
        datap = list_entry(cur,struct score_st,node);
        if(datap->id == 5)
            break;
    }   
    //5.查找结果并打印
    if(cur == &head)
        printf("can not find \n");
    else
        print_s(datap);
    exit(0);
}
View Code

$:make main

ps:内核的代码可以查看:

root # cd /usr/src/kernels/2.6.32-358.el6.x86_64/include/linux/

查找关键字:

root # grep "#define container_of(" -R .
//.  --->当前路径
//R--->递归查找

涉及到的.h文件有:

  kernel.h-----container_of

  list.h---------双向循环链表的实现

  stddef.h-----offsetof

以上是关于数据结构-内核的双向循环链表-简单实现的主要内容,如果未能解决你的问题,请参考以下文章

双向循环链表:鸿蒙轻内核中数据的“驿站”

双向循环链表:鸿蒙轻内核中数据的“驿站”

第33课 双向循环链表的实现

《链表》之带头双向循环链表

带头双向循环链表 代码实现 review

数据结构:如何用C语言快速实现带头双向循环链表