• contiki源码阅读之list


    我们阅读一下contiki的源码,list.c(路径是./core/lib/list.h).

    #include "lib/list.h"
    
    #define NULL 0
    
    struct list {
      struct list *next;
    };

    这就是核心结构体了,发现了吗?没有数据域,成员就是一个指针。其实这个有点类似Linux里面的链表,对,就是嵌入在结构体里面的那个list.我们继续往下看。

    void
    list_init(list_t list)
    {
      *list = NULL;
    }

    初始化函数,这里要说明的是,list_t 就是void**类型。

    在头文件中,有这样的定义:

    #define LIST_CONCAT2(s1, s2) s1##s2
    #define LIST_CONCAT(s1, s2) LIST_CONCAT2(s1, s2)

    #define LIST(name) 
             static void *LIST_CONCAT(name,_list) = NULL; 
             static list_t name = (list_t)&LIST_CONCAT(name,_list)
    

    其实就是定义一个链表(假设name是hello).   有个变量叫hello_list, 其实是一个void*类型的指针,初始化为NULL,这个链表的名字叫hello, hello是指向hello_list的二级指针。

    这里的list是没有头节点的,*hello就得到了第一个元素。因为每个元素都是指针,那么初始化的时候,第一个元素自然为NULL了,表示链表为空。

    void *
    list_head(list_t list)
    {
      return *list;
    }
    返回链表的第一个元素。


    void *
    list_tail(list_t list)
    {
      struct list *l;
      
      if(*list == NULL) {
        return NULL;
      }
      
      for(l = *list; l->next != NULL; l = l->next);
      
      return l;
    }
    返回链表的最后一个元素。


    void
    list_remove(list_t list, void *item)
    {
      struct list *l, *r;
      
      if(*list == NULL) {
        return;
      }
      
      r = NULL;//r用来保存前一个元素
      for(l = *list; l != NULL; l = l->next) {
        if(l == item) {
          if(r == NULL) {//说明要删除的元素恰好是第一个
    	/* First on list */
    	*list = l->next;
          } else {
    	/* Not first on list */
    	r->next = l->next;
          }
          l->next = NULL;
          return;
        }
        r = l;
      }
    }
    删除某个元素。(千万要记住,这个链表的元素就是指针!)


    void
    list_add(list_t list, void *item)
    {
      struct list *l;
    
      /* Make sure not to add the same element twice */
      list_remove(list, item);
    
      ((struct list *)item)->next = NULL;
      
      l = list_tail(list);//得到最后一个元素
    
      if(l == NULL) {
        *list = item;
      } else {
        l->next = item;
      }
    }
    把元素追加到末尾。


    void
    list_push(list_t list, void *item)
    {
    
      /* Make sure not to add the same element twice */
      list_remove(list, item);
    
      ((struct list *)item)->next = *list;
      *list = item;
    }
    头插元素。


    void *
    list_chop(list_t list)
    {
      struct list *l, *r;
      
      if(*list == NULL) {
        return NULL;
      }
      if(((struct list *)*list)->next == NULL) {//说明只有一个元素
        l = *list;
        *list = NULL;
        return l;
      }
      
      for(l = *list; l->next->next != NULL; l = l->next);//查找到倒数第二个元素
    
      r = l->next;
      l->next = NULL;
      
      return r;
    }
    ”弹出“最末尾的一个元素。


    void *
    list_pop(list_t list)
    {
      struct list *l;
      l = *list;
      if(*list != NULL) {
        *list = ((struct list *)*list)->next;
      }
    
      return l;
    }
    “弹出”第一个元素。


    其他函数代码都很简单,我们不再赘述。

    有的朋友不禁要问了,这样的一个链表,怎么用呢?答案下次揭晓,下次我们结合内存管理,举例说明这个链表的用法。







  • 相关阅读:
    将各种简单算法组合,使自己更加灵活的使用它
    转载 原反补码
    迭代器是神马东西
    进程 线程
    STL中的容器是如何实现的,如何存储的
    可以实例化对象,但是不能被继承的类
    float的存储及和int的转化
    对批处理、多道操作系统的理解
    STL set、map实现为什么要以红黑树为底层实现机制?
    c 多线程
  • 原文地址:https://www.cnblogs.com/longintchar/p/5224439.html
Copyright © 2020-2023  润新知