我们阅读一下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;
}

“弹出”第一个元素。

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

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

contiki源码阅读之list的更多相关文章

  1. contiki源码阅读之mmem.c

    上次我们说了list,这次我们就借着mmem.c的代码来用一下这个链表. 代码目录是./core/lib/mmem.c 结构体定义如下 struct mmem { struct mmem *next; ...

  2. Contiki源码结构

    Contiki源码结构 apps目录下,用于存放Application,也就是我们的应用程序放在这个目录下.如webserver,webrowser等,如下图所示. core目录是contiki操作系 ...

  3. 【原】FMDB源码阅读(三)

    [原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...

  4. 【原】FMDB源码阅读(二)

    [原]FMDB源码阅读(二) 本文转载请注明出处 -- polobymulberry-博客园 1. 前言 上一篇只是简单地过了一下FMDB一个简单例子的基本流程,并没有涉及到FMDB的所有方方面面,比 ...

  5. 【原】FMDB源码阅读(一)

    [原]FMDB源码阅读(一) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 说实话,之前的SDWebImage和AFNetworking这两个组件我还是使用过的,但是对于 ...

  6. 【原】AFNetworking源码阅读(六)

    [原]AFNetworking源码阅读(六) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这一篇的想讲的,一个就是分析一下AFSecurityPolicy文件,看看AF ...

  7. 【原】AFNetworking源码阅读(五)

    [原]AFNetworking源码阅读(五) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇中提及到了Multipart Request的构建方法- [AFHTTP ...

  8. 【原】AFNetworking源码阅读(四)

    [原]AFNetworking源码阅读(四) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇还遗留了很多问题,包括AFURLSessionManagerTaskDe ...

  9. 【原】AFNetworking源码阅读(三)

    [原]AFNetworking源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇的话,主要是讲了如何通过构建一个request来生成一个data tas ...

随机推荐

  1. 用create table 命令建立表

    create table [[V.]HANKE.].MADE IN HOME (xuliehao int primary key, name varchar(20)not null, jiage fl ...

  2. ASP.NET MVC 视图层-生成链接相关(Html.ActionLink,Url.Action)

    1. @Html.ActionLink()  参考 也是使用在chtml模板中,返回参数中指定controller.指定action的所生成的超链接标签<a>标签html文本.如果没有指定 ...

  3. mvvm模式下在WPF项目中动态加载项目的程序集和类

    在mvvm模式的wpf项目中有个需求需要去加载解决方案的程序集,并且根据程序集去动态加载当前程序集的类,做成下拉框形式. 效果: //全局定义 private ComboBox abList= nul ...

  4. 利用BIND搭建自己的私有根及授权域

    这篇文章是对之前博客写的DNS的再深一层的搭建,其中包括搭建私有根,还有顶级域以及授权子域,转发域,反向解析等等 上一篇DNS的博客链接:http://www.cnblogs.com/hjc4025/ ...

  5. 毛玻璃CHBlurEffect

    1.将需要加入毛玻璃的UI控件传入接口即可 1.1 .h文件 // // 文 件 名:CHBlurEffect.h // // 版权所有:Copyright © 2018年 leLight. All ...

  6. Linux定时任务(crond)

    1.Crond定义 crond是Linux系统中用来定期执行命令或指定程序的一种服务或软件. (1)linux系统自身定期执行的任务(轮询系统日志.备份数据等) (2)用户执行的任务(定时更新同步时间 ...

  7. 用ES6的class模仿Vue写一个双向绑定

    原文地址:用ES6的class模仿Vue写一个双向绑定 点击在线尝试一下 最终效果如下: 构造器(constructor) 构造一个TinyVue对象,包含基本的el,data,methods cla ...

  8. windows mysql导入sql文件

    当需要的sql文件很大时(>200M)怎么办?答:修改my.ini文件,max_allowed_packet的值可以设置为1024M 进入mysql.exe目录下,执行如下命令: mysql - ...

  9. docker的常用操作

    查看所有的镜像: docker images 查看所有的容器: docker ps -a 查看正在运行的容器: docker ps 移除容器: docker rm -f 容器id 移除镜像: dock ...

  10. AngularJS页面【uib-dropdown】控件在模态窗口(弹出窗)中无法使用问题

    如果你的下拉框中有属性 dropdown-append-to-body 将它去掉,即可正常使用该插件. <div class="btn-group dropdown" uib ...