您的位置:首页 > 产品设计 > UI/UE

queue.h的链表使用

2016-08-29 10:11 316 查看
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: