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;
}
“弹出”第一个元素。


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

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







你可能感兴趣的:(链表contiki)