内核链表和普通链表的理解
他们都是容器,存需要的东西用的。
普通链表:每次指针指向的节点的首地址,因此非常好访问节点的各个member的数据。
内核链表就不一样了:定义了List_head,之后的节点指向都是节点的里面的list指针域,因此它不是这个结构体的首地址,因此想访问整个结构体变量,就必须采用一种骚操作,得到这个结构体变量首地址,然后就好访问成员。
相同点:都是采用递归 也是for循环 或者while循环 指针往后移
不同点:内核链表多了一步骚操作,会通过一个特殊宏得到结构体变量的首地址
// Queue.cpp : 定义控制台应用程序的入口点。 #include "stdafx.h" #include <stdio.h> #include <string.h> #include <stddef.h> // 注意没有这个会导致编译器报错 #include <math.h> struct list_head { struct list_head *next; struct list_head *prev; }; /* one-shot definition of a list head */ #define LIST_HEAD(x) \ struct list_head x = { &x, &x } /* initialize a list head explicitly */ static inline void INIT_LIST_HEAD(struct list_head *p) { p->next = p->prev = p; } #define list_entry_offset(p, type, offset) \ ((type *)((char *)(p) - (offset))) /* list_entry - retrieve the original struct from list_head * @p: list_head pointer * @type: struct type * @member: struct field member containing the list_head */ #define list_entry(p, type, member) \ list_entry_offset(p, type, offsetof(type, member)) /* list_for_each - iterate over the linked list * @p: iterator, a list_head pointer variable // 迭代 重复 list_head类型的指针变量 * @list: list_head pointer containing the list */ #define list_for_each(p, list) \ for (p = (list)->next; p != (list); p = p->next) /* list_for_each_safe - iterate over the linked list, safe to delete * @p: iterator, a list_head pointer variable * @s: a temporary variable to keep the next, a list_head pointer, too * @list: list_head pointer containing the list */ #define list_for_each_safe(p, s, list) \ for (p = (list)->next; s = p->next, p != (list); p = s) /* list_add - prepend a list entry at the head * @p: the new list entry to add * @list: the list head */ static inline void list_add(struct list_head *p, struct list_head *list) { struct list_head *first = list->next; p->next = first; first->prev = p; list->next = p; p->prev = list; } /* list_add_tail - append a list entry at the tail * @p: the new list entry to add * @list: the list head */ static inline void list_add_tail(struct list_head *p, struct list_head *list) { struct list_head *last = list->prev; last->next = p; p->prev = last; p->next = list; list->prev = p; } /* list_insert - insert a new list entry between two known consecutive entries * @p: the new entry to be inserted between prev and next * @prev: the left-side entry * @next: the right-side entry */ static inline void list_insert(struct list_head *p, struct list_head *prev, struct list_head *next) { next->prev = p; p->next = next; p->prev = prev; prev->next = p; } /* list_del - delete the given list entry */ static inline void list_del(struct list_head *p) { p->prev->next = p->next; p->next->prev = p->prev; } /* list_empty - returns 1 if the given list is empty */ static inline int list_empty(const struct list_head *p) { return p->next == p; } struct int_node { int val; int num; struct list_head list; }; int main() { struct list_head head, *plist; struct int_node a, b, c; struct int_node *node; a.val = 1; a.num = 1; b.val = 2; b.num = 2; c.val = 3; c.num = 3; INIT_LIST_HEAD(&head); list_add_tail(&a.list, &head); list_add_tail(&c.list, &head); int count = 0; printf("************遍历链表,打印结果**************\n"); list_for_each(plist, &head) { //node = list_entry(plist, struct int_node, list); //printf("val = %d, num = %d\n", node->val, node->num); node = list_entry(plist, struct int_node, list); count++; printf("count is %d\n", count); printf("val = %d, num = %d\n", node->val, node->num); } printf("************删除节点b,重新遍历链表,打印结果*\n"); //list_del(&b.list); list_for_each(plist, &head) //就是一个for循环 指向下个节点 list_head的指针 { node = list_entry(plist, struct int_node, list); // 得到当前节点的首地址 实现原理:知道我们当前在哪里,也知道偏移量, 两者相减就可以得到变量的首地址 printf("val = %d, num = %d\n", node->val, node->num); // 基于得到结构体变量的首地址 访问里面的数据成员 }//print 1 1 3 3 printf("************打印链表head1******************\n"); struct int_node d, e; struct list_head head1; d.val = 4; d.num = 4; e.val = 5; e.num = 5; INIT_LIST_HEAD(&head1); list_add_tail(&d.list, &head1); list_add_tail(&e.list, &head1); list_for_each(plist, &head1) { struct int_node *node = list_entry(plist, struct int_node, list); printf("val = %d, num = %d\n", node->val, node->num); } while (1); printf("*******************************************\n"); if (!list_empty(&head)) { printf("the list is not empty!\n"); } while (1); return 0; }
一勤天下无难事。