__list_add()的功能是在两个非空结点中插入一个结点,值得注意的是new、prev、next均不能为空值。当然prev可以等于next,此时表示在只含头节点的链表中插入新节点。知道了__list_add()函数的实现我们接下来当然也要看看list_add()和list_add_tail()的实现。
- 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);
- }
|
看了上面的实现方式我们知道他们都是调用底层的__list_add()来实现的。看看在__list_add()函数里面传递不同的参数我们就能实现不同的添加节点的方法。__list_add()函数前面的双划线通常表示这是一个底层函数,供其他的模块调用。
第一个list_add()传递的参数实现的是在head和head->next两指针所指向的结点之间插入new所指向的结点。即就是在head指针的后面插入一个new所指向的结点。Head并非一定为头结点。如果我们的链表只含有一个头节点时,上面的__list_add(new, head, head->next)仍然成立。
第二个list_add_tail()其功能是在结点指针head所指向结点的前面插入new所指向的结点。当如果head指向的是头结点,那么就相当于在尾结点后面增加一个new所指向的结点。在这个函数里值得注意的是head->prev不能为空,如果head为头结点,那么head->prev要指向一个数值,一般为指向尾结点,构成循环链表。
说到这儿可能有的读者已经迫不及待的想看看代码了,那我们就用linux内核里的list.h在应用层来写出我们的代码。
- #include <stdio.h>
- #include <stdlib.h>
- #include "list.h"
-
- typedef struct _stu
- {
- char name[20];
- int num;
- struct list_head list;
- }stu;
-
- int main()
- {
- stu *pstu;
- stu *tmp_stu;
- struct list_head stu_list;
- struct list_head *pos;
- int i = 0;
-
- INIT_LIST_HEAD(&stu_list);
-
- pstu = malloc(sizeof(stu)*5);
-
- for(i=0;i<5;i++)
- {
- sprintf(pstu[i].name,"Stu%d",i+1);
- pstu[i].num = i+1;
- list_add( &(pstu[i].list), &stu_list);
- }
-
- list_for_each(pos,&stu_list)
- {
- tmp_stu = list_entry(pos, stu, list);
- printf("student num: %d\tstudent name: %s\n",tmp_stu->num,tmp_stu->name);
- }
- free(pstu);
- return 0;
- }
|
运行结果为:
- root@ubuntu:/home/paixu/dlist_node# ./a
- student num: 5 student name: Stu5
- student num: 4 student name: Stu4
- student num: 3 student name: Stu3
- student num: 2 student name: Stu2
- student num: 1 student name: Stu1
|