关闭

queue.h的链表使用

338人阅读 评论(0) 收藏 举报
分类:

from  https://segmentfault.com/a/1190000000596749

在FreeBSD中有queue.h这样一个头文件(Linux也有),它定义了一系列的宏操作,实现了链表,尾队列和循环链表。其中,链表的功能最为简单,效率是最好的。
我们先看一下系统提供的链表的操作:

    LIST_ENTRY(TYPE)   
    LIST_HEAD(HEADNAME,TYPE)
    LIST_INIT(LIST_HEAD *head)
    LIST_INSERT_AFTER(LIST_ENTRY *listelm,TYPE *elm,LIST_ENTRY NAME)
    LIST_INSERT_HEAD(LIST_HEAD *head,TYPE *elm,LIST_ENTRY NAME)
    LIST_REMOVE(TYPE *elm,LIST_ENTRY NAME)

其中LIST_HEAD、LIST_INIT、LIST_INSERT_AFTER、LIST_INSERT_HEAD、LIST_REMOVE从名字可以看出其功能,但是它们的参数就不这么好理解了。下面我们来看一个例子和部分宏的源码,弄明白这组宏的使用方法。
部分宏源码

#define LIST_ENTRY(type)                                                \
struct {                                                                \
        struct type *le_next;   /** next element */                     \
        struct type **le_prev;  /** address of previous next element */ \
}
#define LIST_HEAD(name, type)                                           \
struct name {                                                           \
        struct type *lh_first;  /** first element */                    \
}
#define LIST_INSERT_HEAD(head, elm, field) do {                         \
        if (((elm)->field.le_next = (head)->lh_first) != NULL)          \
                (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
        (head)->lh_first = (elm);                                       \
        (elm)->field.le_prev = &(head)->lh_first;                       \
} while (/**CONSTCOND*/0)



example

#include<stdio.h>
#include<stdlib.h>
#include<sys/queue.h>

struct element{
    int num;
    /*LIST_ENTRY 创建了一个以element为名的结构体定义
     这个结构体含有向后指针和向前指针
     le_next 和 le_prev
     并且声明了一个类型为element的变量elements
     */
    LIST_ENTRY(element) elements;
};
int main(void){
    /*LIST_HEAD 会自动构建一个名为listh的结构体,
      里面含有一个element指针 *lh_first
      所以 先调用LIST_HEAD之后,才会生成struct声明,后面才可以使用
      关于listh的指针
     */
    LIST_HEAD(listh,element) head; 
    struct listh *headp;
    struct element *n1,*np;
    int i=0;
    LIST_INIT(&head);
    printf("开始\n");
    do{

        printf("输入一个数字,输入0则结束\n");
        scanf("%d",&i);

        n1 = (struct element*)malloc(sizeof(struct element));
        n1->num = i;

        /*
       对于LIST_INSERT_HEAD为何需要用指针域作为参数,
       因为指针域的名字是用户自己定义的,函数内部并不知道,
       所以需要作为参数传入,并且在宏之内,可以连接字符串实现
       类似反射的功能。
       */

        LIST_INSERT_HEAD(&head,n1,elements);
    }while(i);
    for(np=(head).lh_first;np!=NULL;np=np->elements.le_next){
        printf("%d ",np->num);
    }   
    printf("\n");
    return 0;
}




0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:189928次
    • 积分:2563
    • 等级:
    • 排名:第14839名
    • 原创:17篇
    • 转载:309篇
    • 译文:0篇
    • 评论:10条
    文章分类
    最新评论