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. docker登录没有配置https的harbor镜像仓库

    已经搭建harbor 仓库 ,域名  172.16.1.99 出现问题: 客户端尝试登录 仓库 [root@localhost docker]# docker login 172.16.1.99:80 ...

  2. 获取网站资源 getResourceAsStream

    获取网站资源(重点) public void doGet(HttpServletRequest request, HttpServletResponse response)throws Servlet ...

  3. 设置sqlplus访问远程oracle数据库的最快方法

    设置sqlplus访问远程oracle数据库的最快方法 时间:2010-01-21 10:57来源: 作者: 点击: 2次 设置sqlplus访问远程oracle数据库的最快方法,如果要连接远程数据库 ...

  4. MFC图形绘制——绘制直尺和坐标系

    一.实验目的 1.掌握建立MFC应用程序的方法: 2.掌握映射模式. 二.实验内容 1.在MFC中绘制直尺,直尺需要有刻度,类似于日常学生使用的透明塑料直尺,需要建立四个直尺,分别分布在屏幕客户区的上 ...

  5. 使用 HTML5 History 新特性增强 Ajax 的体验(转)

    一. 场景再现 如大家熟知,Ajax 可以实现页面的无刷新操作,但会造成两个与普通页面操作(有刷新地改变页面)有着明显差别的问题—— URL 没有修改以及无法使用前进.后退按钮.例如常见的 Ajax ...

  6. mvc中Action前HttpPost的作用

    本文导读:在ASP.NET MVC框架中,为了限制某个action只接受HttpPost的请求,对于HttpGet的请求则提示404找不到页面,可以在action的方法前面加上[HttpPost]属性 ...

  7. Python学习笔记014——生成器Generator

    1 生成器定义 在Python中,一边循环一边计算的机制,称之为生成器(generator). 生成器是一个迭代器. 含有yield语句的函数是生成器函数,该函数被调用时返回一个生成器对象(yield ...

  8. Shlwapi.h头文件的使用

    // TestShlwAPI.cpp : 定义控制台应用程序的入口点.// #include "stdafx.h"#include <Shlwapi.h>#pragma ...

  9. Spring Cloud 通过代码自定义配置Ribbon

    我们还是先从官网文档开始学习,如下图所示,我们可以搞一个测试配置类,来验证是否真的可以通过代码来自定义配置Ribbon,但文档明确给出了警告:即这个测试配置类不能放在@ComponentScan所扫描 ...

  10. ASP.NET 解决URL中文乱码的解决

    暂时先记录一个方法: 在Web.config文件中configuration下的system.web下加入一个配置项:globalization,主要是设置其requestEncoding,貌似中文系 ...