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. c:forEach标签

    //varStat代表 遍历typeListDesc集合所用到的方法 <!-- stat当前迭代的第几项 --> <c:forEach var="type" it ...

  2. archlinux使用sudo

    Sudo是允许系统管理员让普通用户执行一些或者全部的root命令的一个工具,如halt,reboot,su等等.这样不仅减少了root用户的登陆 和管理时间,同样也提高了安全性. Sudo不是对she ...

  3. HDUOJ----2952Counting Sheep

    Counting Sheep Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  4. nyoj------擅长排列的小明

    擅长排列的小明 时间限制:1000 ms  |           内存限制:65535 KB 难度:4   描述 小明十分聪明,而且十分擅长排列计算.比如给小明一个数字5,他能立刻给出1-5按字典序 ...

  5. POJ 3233 Matrix Power Series (矩阵乘法)

    Matrix Power Series Time Limit: 3000MS   Memory Limit: 131072K Total Submissions: 11954   Accepted:  ...

  6. ubuntu 忘记root密码了不用怕,看这里

    方法来自这里:http://jingyan.baidu.com/article/8065f87fe20832233024985a.html

  7. mongoDB系列之(二):mongoDB 副本集

    1. 什么是副本集 副本集就是mongoDB副本所组成的一个集群. 同期原理是,写操作发生在主库,从库同步主库的OpLog日志. 集群中没有特定的主库,主库是选举产生,如果主库down了,会再选举出一 ...

  8. ios 中的tintColor

    在iOS 7后,UIView新增加了一个tintColor属性,这个属性定义了一个非默认的着色颜色值,其值的设置会影响到以视图为根视图的整个视图层次结构.它主要是应用到诸如app图标.导航栏.按钮等一 ...

  9. 转 HTTP协议 (四) 缓存

    转自:http://www.cnblogs.com/TankXiao/archive/2012/11/28/2793365.html 缓存的概念 缓存这个东西真的是无处不在, 有浏览器端的缓存, 有服 ...

  10. RHCE7 -- IPv6

    IPV6地址一个128位数字   如果在IPv6地址后面包括TCP和UDP网络端口,建议将IPv6放在方括号中,以便区分: [2001:db8:0:10::1]:80   IPv6的标准子网掩码是&q ...