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. HDUOJ-----2175取(m堆)石子游戏

    取(m堆)石子游戏 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

  2. Pycharm中 import 引入同级文件失败问题

    Pycharm中 import 引入同级文件失败,如下所示:  “This inspection detects names that should resolve but don't. Due to ...

  3. php计算经纬度间的距离

    <?php //根据经纬度计算距离 function getdistance($lng1,$lat1,$lng2,$lat2) { //将角度转为狐度 $radLat1=deg2rad($lat ...

  4. MySQL数据库查询优化建议

    1. 对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2. 应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使 ...

  5. poj 3735 Training little cats(构造矩阵)

    http://poj.org/problem?id=3735 大致题意: 有n仅仅猫,開始时每仅仅猫有花生0颗,现有一组操作,由以下三个中的k个操作组成: 1. g i 给i仅仅猫一颗花生米 2. e ...

  6. 怎样让VMware上的虚拟机ping通外网(图解教程)

    近期在实习项目中遇到一个问题. 因測试须要,本人在win7上安装VMWare后在启动两台ubuntuserver.两台主机的网络配置所有採用NAT方式实现连接. 之后一路畅通.主机ping通虚拟机和外 ...

  7. unity 主循环

    在unity官方文档中看到这个图,感觉很有用,各事件的先后时机看得较清楚. 连接:http://docs.unity3d.com/Manual/ExecutionOrder.html

  8. Oracle学习笔记之一,重温范式

    第一范式(1NF) 第一范式是第二和第三范式的基础,是最基本的范式.第一范式包括下列的指导原则: 数据组的每个属性只可以包含一个值. 关系中的每个数组必须只包含相同数量的值. 关系中的每个数组一定不能 ...

  9. 【备用】SQL SERVER存储过程执行速度慢的问题

    今天看到了但是暂时没有时间研究,先留着备用(Parameter Sniffing) http://blog.csdn.net/emili/article/details/2192081 http:// ...

  10. [svc][op]LVS+keepalived

    lvs是一种负载均衡技术.注意区分负载均衡和高可用的区别. keepalive是lvs的管理工具 ipvsadm也是lvs的管理工具 keepalive借助ipvsadm管理lvs.所以通常说lvs+ ...