1 相关宏和数据结构

1.1 LIST_CONCAT

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

该宏的作用非常简单,将s1,s2拼接在一起。其中,##起连接作用,编译器在预处理时负责将s1,s2连接在一起。比如hello_##world经过编译器预处理后就变成了hello_world了。

1.2 LIST

typedef void ** list_t;

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

经过宏替换后,变为

#define LIST(name) \
static void *name_list = NULL; \
static list_t name = (list_t)&name_list

该宏用于申明一个链表。可以将name_list理解为链表头(且该表头元素是一个指针),将name理解为一个指向链表头的指针。需要注意的是,name_list所指向的类型必须是一个结构体。

1.3 LIST_STRUCT

#define LIST_STRUCT(name) \
void *LIST_CONCAT(name,_list); \
list_t name

1.4 LIST_STRUCT_INIT

#define LIST_STRUCT_INIT(struct_ptr, name)                              \
do { \
(struct_ptr)->name = &((struct_ptr)->LIST_CONCAT(name,_list)); \
(struct_ptr)->LIST_CONCAT(name,_list) = NULL; \
list_init((struct_ptr)->name); \
} while(0)

1.5 struct list

struct list {
struct list *next;
};

struct list只有一个指针成员next,它指向的类型依然是struct list。在Contiki中,该结构体用于用于遍历链表,我们将在后面的链表函数中看到如何使用该结构体。

2 各链表函数

2.1 list_init

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

作用:初始化链表
解释

2.2 list_head

void *
list_head(list_t list)
{
return *list;
}

作用:获取链表头
解释

2.3 list_copy

void
list_copy(list_t dest, list_t src)
{
*dest = *src;
}

作用:“拷贝”链表
解释

2.4 list_tail

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;
}

作用:返回链表尾部节点
解释

2.5 list_add

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;
}
}

作用:在链表尾部加入节点
解释

2.6 list_push

void
list_push(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 = *list;
*list = item;
}

作用:在链表头部压入节点
解释

2.7 list_chop

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;
}

作用:砍掉链表尾部节点,并返回该尾部节点
解释

2.8 list_pop

void *
list_pop(list_t list)
{
struct list *l;
l = *list;
if(*list != NULL) {
*list = ((struct list *)*list)->next;
} return l;
}

作用弹出链表头结点
解释

2.9 list_remove

void
list_remove(list_t list, void *item)
{
struct list *l, *r; if(*list == NULL) {
return;
} r = NULL;
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;
}
}

作用:删除item所指向的节点

解释

2.10 list_length

int
list_length(list_t list)
{
struct list *l;
int n = 0; for(l = *list; l != NULL; l = l->next) {
++n;
} return n;
}

作用:返回链表长度
解释

2.11 list_insert

void
list_insert(list_t list, void *previtem, void *newitem)
{
if(previtem == NULL) {
list_push(list, newitem);
} else { ((struct list *)newitem)->next = ((struct list *)previtem)->next;
((struct list *)previtem)->next = newitem;
}
}

作用:插入链表节点
解释

2.12 list_item_next

void *
list_item_next(void *item)
{
return item == NULL? NULL: ((struct list *)item)->next;
}

作用:返回链表中item的下一个节点

contiki list 链表的更多相关文章

  1. Contiki学习笔记  第一个程序:Hello World

    想来想去,还是得先写一个程序,找下感觉,增强一下自信心,那就国际惯例Hello World吧.先到这个网址下一个Instant Contiki 2.7.之所以没用3.0的,是因为有些问题,我源码是下的 ...

  2. 简单的玩玩etimer <contiki学习笔记之九 补充>

    这幅图片是对前面  <<contiki学习笔记之九>>  的一个补充说明. 简单的玩玩etimer <contiki学习笔记之九> 或许,自己正在掀开contiki ...

  3. PROCESS_YIELD()宏使用及过程分析<contiki学习笔记之八>

    好吧,昨晚上研究了switch()的底层实现原理--发现它并不是一般C语言教科书上那样所言,当然,这对于本身就非常熟悉汇编的同学来说,是小菜一碟.世界上,很多事情是巧合与必然的结合体,没有无缘无故的爱 ...

  4. contiki-main.c 中的process系列函数学习笔记 <contiki学习笔记之六>

    说明:本文依然依赖于 contiki/platform/native/contiki-main.c 文件. ---------------------------------------------- ...

  5. contiki源码阅读之list

    我们阅读一下contiki的源码,list.c(路径是./core/lib/list.h). #include "lib/list.h" #define NULL 0 struct ...

  6. 初识contiki(2.7版本)

    一个偶然的机会,我接触到了contiki这个家伙. Contiki 是一个开源的.高度可移植的.采用 C 语言开发的非常小型的嵌入式操作系统,针对小内存微控制器设计,适用于联网嵌入式系统和无线传感器网 ...

  7. Contiki Etimer 模块

    一.Etimer概述 Etimer提供产生时间事件(timed event)的机制,当设定好的timer到期时,将会给设定etimer的process发送一个PROCESS_EVENT_TIMER 事 ...

  8. Contiki Process概述

    本文涉及到的Protothread机制知识,在http://www.cnblogs.com/songdechiu/p/5793717.html 一.进程类型 进程类型主要有协同式(cooperativ ...

  9. Redis链表实现

    链表在 Redis 中的应用非常广泛, 比如列表键的底层实现之一就是链表: 当一个列表键包含了数量比较多的元素, 又或者列表中包含的元素都是比较长的字符串时, Redis 就会使用链表作为列表键的底层 ...

随机推荐

  1. 【转】SVN与Git比较

    摘要Svn是目前得到大多数人认可,使用得最多的版本控制管理工具,而Git的优势在于易于本地增加分支和分布式的特性,可离线提交,解决了异地团队协同开发等svn不能解决的问题.本文就这两种版本控制工具的异 ...

  2. iOS 直播推流 - 搭建基于RTMP的本地Nginx服务器

    前端时间,公司要调研直播相关的内容,特地花时间进行了一番调研. 本篇将记录其中的推流篇-本地推理播放测试. 关于Nginx: 配置Nginx以支持HLS.RTMP的推流与拉流,iOS系统使用LFLiv ...

  3. HDUOJ----4501小明系列故事——买年货(三维背包)

    小明系列故事——买年货 Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total ...

  4. 【LeetCode】42. Trapping Rain Water

    Trapping Rain Water Given n non-negative integers representing an elevation map where the width of e ...

  5. iphone 如何给cydia添加中文源和威锋源

    http://zhidao.baidu.com/question/270663590.html英文的也没关系, 步骤是这样的, 1. 打开Cydia, 下面有五个项目, 然后选倒数第二个manage, ...

  6. eclipse 在Servers窗口创建一个Tomcat 6.0 Server失败

    web项目部署到tomcat除了用eclipse插件,eclipse也有一个Servers窗口来部署.   问题背景:Servers窗口,我之前创建过一个Tomcat v6.0 Server,后来我把 ...

  7. 利用pushState开发无刷页面切换(转)

    相关文档:https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulatingthebrowser_history 实现目标 ...

  8. 转 Python标准库01 正则表达式 (re包)

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 我将从正则表达式开始讲Python的标准库.正则表达式是文字处理中常用的工具,而且 ...

  9. Spring.net(二)----初探IOC容器

    我在上一篇关于Spring.net的文章“Spring.NET框架简介及模块说明 ”中很详细的介绍了,本文就不旧话从提.我门就直奔主题吧. 1.首先了解两个接口.  IObjectFactory接口和 ...

  10. 内存管理算法--Buddy伙伴算法【转】

    转自:http://blog.csdn.net/orange_os/article/details/7392986 Buddy算法的优缺点: 1)尽管伙伴内存算法在内存碎片问题上已经做的相当出色,但是 ...