list.h 中的包含的代码如下:

    #ifndef LIST_H
    #define LIST_H
    #include "darknet.h"
    
    // 初始化链表
    list *make_list();
    // 按值查找,注意这里的值是 void类型空指针,emmmm, list.c未定义,
    int list_find(list *l, void *val); 
    
    //
    void list_insert(list *, void *);
    
    
    void free_list_contents(list *l);
    
    #endif

    首先,我们分析list.h 中的源码,基础数据结构list 定义在 darknet.h 中,其定义如下:

    typedef struct node{
        void *val; // 当前节点的内容是一个void类型的空指针
        struct node *next; //指向当前节点的下一节点
        struct node *prev; //指向当前节点的上一节点
    } node;
    
    typedef struct list{
        int size; // 当前list 的长度
        node *front; // 头指针,指针链表第一个节点
        node *back;  //尾指针,指针链表最后一个节点
    } list;

    可以发现,list就是我们熟悉的链表,可以发现在 list.h 中定义了4个函数,下面我们分别对解析这4个函数,我们将注解写在 list.c中,如下:

    #include <stdlib.h>
    #include <string.h>
    #include "list.h"
    
    
    // 初始化链表
    list *make_list()
    {
        // 分配存储空间
        list *l = malloc(sizeof(list));
        // 初始化链表长度、头指针、尾指针
        l->size = 0; 
        l->front = 0;
        l->back = 0;
        return l;
    }
    
    /*
    void transfer_node(list *s, list *d, node *n)
    {
        node *prev, *next;
        prev = n->prev;
        next = n->next;
        if(prev) prev->next = next;
        if(next) next->prev = prev;
        --s->size;
        if(s->front == n) s->front = next;
        if(s->back == n) s->back = prev;
    }
    */
    
    // 链表的删除操作,删除尾指针所指节点,即最后一个节点
    void *list_pop(list *l){
        // 如果链表为空
        if(!l->back) return 0;
        // node *b 指向最后一个节点
        node *b = l->back;
        void *val = b->val;
        // 更新尾指针,尾指针指向b的前一节点,即倒数第二节点。
        l->back = b->prev;
        // 如果倒数第二节点存在
        if(l->back) l->back->next = 0; //尾指针next置为null
        free(b); // 释放最后一个节点的存储空间
        --l->size; // 链表长度 -1
    
        return val; // 返回被删除节点保存的值
    }
    
    // 链表按序插入操作
    void list_insert(list *l, void *val)
    {
        // 为新节点申请存储空间
        node *new = malloc(sizeof(node));
        // 赋值
        new->val = val;
        new->next = 0; // next置null
    
        // 如果链表l 尾指针为空,则说明此时链表l长度为0
        if(!l->back){
            l->front = new; // 更新头指针
            new->prev = 0; // 此时该节点为头节点,故头节点的上一节点为null
        }else{ //如果链表l 尾指针非空,则说明此时l长度 >=1
            l->back->next = new; // 更新当前节点的上一节点的next指针域
            new->prev = l->back; // 更新当前节点的prev指针域
        }
        l->back = new; // 更新链表l的尾指针
        ++l->size; // 链表长度 +1 
    }
    
    // 释放链表节点的存储空间,从节点n开始释放,一直释放到最后一个节点。
    void free_node(node *n)
    {
        node *next;
        while(n) {
            next = n->next; // 获取下一节点地址
            free(n); // 释放当前节点存储空间
            n = next; //更新n,n指向下一节点
        }
    }
    
    // 释放整个链表l的存储空间
    void free_list(list *l)
    {
        free_node(l->front);
        free(l);
    }
    
    // 对链表所有节点的值【节点中值为void 类型指针】 的存储空间释放
    void free_list_contents(list *l)
    {
        node *n = l->front;
        while(n){
            free(n->val);
            n = n->next;
        }
    }
    
    // 二维指针,这里的操作是将链表l中所有节点的值进行保存,
    // 因为每个节点里保存的值是 void类型的指针,故指针的指针,即二维指针
    void **list_to_array(list *l)
    {
        // 分配存储空间,长度l-size, 每个空间大小为一个void类型指针
        void **a = calloc(l->size, sizeof(void*));
        int count = 0;
        node *n = l->front; // 工作指针n指向头节点
        while(n){
            // 将工作指针n指向节点的值保存到a中
            a[count++] = n->val;
            n = n->next;// 更新工作指针
        }
        return a;
    }