• 内核链表和普通链表的理解


                                            他们都是容器,存需要的东西用的。   

                                        普通链表:每次指针指向的节点的首地址,因此非常好访问节点的各个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("************遍历链表,打印结果**************
    ");
        list_for_each(plist, &head)
        {
            //node = list_entry(plist, struct int_node, list);
            //printf("val = %d, num = %d
    ", node->val, node->num);
            node = list_entry(plist, struct int_node, list);
            count++;
            printf("count is %d
    ", count);
            printf("val = %d, num = %d
    ", node->val, node->num);
        }
        
        
        printf("************删除节点b,重新遍历链表,打印结果*
    ");
        //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
    ", node->val, node->num); // 基于得到结构体变量的首地址  访问里面的数据成员
        }//print 1 1 3 3
        printf("************打印链表head1******************
    ");
        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
    ", node->val, node->num);
        }
    
        while (1);
        printf("*******************************************
    ");
        if (!list_empty(&head))
        {
            printf("the list is not empty!
    ");
    
        }
        while (1);
    
        return 0;
    }

    一勤天下无难事。
  • 相关阅读:
    雷林鹏分享:Mysql 连接的使用
    雷林鹏分享:MySQL GROUP BY 语句
    雷林鹏分享:MySQL 排序
    雷林鹏分享:MySQL UNION 操作符
    雷林鹏分享:MySQL LIKE 子句
    雷林鹏分享:MySQL DELETE 语句
    好用的工具库
    免费的自动构建CI
    如何减少block的嵌套层次?
    一些ios牛人的博客
  • 原文地址:https://www.cnblogs.com/nowroot/p/12733903.html
Copyright © 2020-2023  润新知