contiki源码阅读之list

本文深入剖析了Contiki操作系统中的链表实现方式,包括其核心结构体定义、初始化过程及关键操作函数如添加、删除、获取头尾元素等。特别介绍了如何通过宏定义简化链表的创建,并展示了链表维护的具体细节。

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


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

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







In this book I present an analysis course which I have teach to first year graduate students at the Univereity of Wisconsin since 1962. The course was developed for two reasons. The first was a belief that one could present the basic techniques and theorems of analysis in one year, with enough applications to make the subject interesting, in such a way that students could then specialize in any direction they choose. The second and perhaps even more important one was the desire to do away with the outmoded and misleading idea that analysis consists of two distinct halves, "real variables" and "complex variables.'' Traditionally (with some oversimplification) the first of these deals with Lebesgue integration, with various types of convergence, and with the pathologies exhibited by very discontinuous functions; whereas the second one concerns itself only with those functions that are as smooth rts can be, namely, the holomorphic ones. That these two areas interact most intimately has of course been well known for at least 60 years and is evident to anyone who is acquainted with current research. Nevertheless, the standard curriculum in most American universities still contains a year course in complex variables, followed by a year course in real variables, and usually neither of these courses acknowledges the existence of the subject matter of the other. I have made an effort to demonstrate the interplay among the various parts of analysis, including some of the basic ideas from functional analysis. Here are a few examples. The Riesz representation theorem and the Hahn-Banach theorem allow one to "guess" the Poisson integral formula. They team up in the proof of Runge's theorem, from which the homology version of Cauchy's theorem follows easily. They combine with Blaschke's theorem on the zeros of bounded holomorphic functions to give a proof of the Miintz-Szasz theorem, which concerns approximation on an interval. The fsct that LZ is a Hilbert space is used in the proof of the W o n - N i i y m theorem, which leads to the theorem ,about differentiation of indefinite integrals (incidentally, daerentiation seems to be unduly slighted in most modern texts), which in turn yields the existence of radial limits of bounded harmonic functions. The theorems of Plancherel and Cauchy combined give a theorem of Paley and Wiener which, in turn, is used in the Denjoy-Carleman theorem about infinitely differentiable functions on the real lime. The maximum modulus theorem gives information about linear transformations on Lp-spsces. Since most of the results presented here are quite classical (the novelty lies in the arrangement, and some of the proofs are new), I have not attempted to document the source of every item. References are gathered at the end, in Notes and Comments. They are not always to the original sources, but more often to more recent works where further references can be found. In no case does the absence of a reference imply any claim to originality on my part. The prerequisite for this book is a good course in advanced calcuIus (set-theoretic manipulations, metric spaces, uniform continuity, and uniform convergence). The first seven chapters of my earlier book "Principles of Mathematical Adysis" furnish smcient preparation.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值