我们阅读一下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. zen coding

    zen-Coding是一款快速编写HTML,CSS(或其他格式化语言)代码的编辑器插件,这个插件可以用缩写方式完成大量重复的编码工作,是web前端从业者的利器. zen-Coding插件支持多种编辑器 ...

  2. DjVu、PDF中的隐藏文本

    作者:马健邮箱:stronghorse_mj@hotmail.com发布:2012.06.11 目录一.背景二.DjVu中的隐藏文本三.PDF中的隐藏文本 一.背景 目前对于扫描电子文档,网上比较流行 ...

  3. 为PyCharm配置QT

    由于QT在创建窗体项目时会自动生成后缀名为ui的文件,该文件需要转换为py文件后才可以被python所识别,所有需要为QT与PyCharm开发工具进行配置,具体步骤如下: (1)确保Python.QT ...

  4. winform GDI基础(四)简单截屏

    Bitmap bitmap = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height); G ...

  5. SQLServer存储引擎——02.内存

    SQLServer存储引擎之内存篇: (1)SQL SERVER 内存结构        SQL SERVER 内存结构简图 SQL SERVER 内存空间主要可分为两部分: (1.1)可执行代码(E ...

  6. C#读取文本文件某一行

    某一时候,我们只会读取文本文件内某一行.怎样读?还是用for或foreach循环?其实操作起来,很简单,先看看文本文件,如果你也想用下面的文档来做测试,你可以在这个链接进行拷贝:<VB.NET提 ...

  7. javascript jquery插入元素后事件会被注销

      js jquery插入元素后事件会被注销 document.body.innerHTML += <div id="dd">test</div>  //这 ...

  8. poj1195(二维树状数组)

    题目链接:https://vjudge.net/problem/POJ-1195 题意:有s*s的矩阵,初始化为全0,有两种操作,单点修改(x,y)的值,区间查询(x,y)的值(l<=x< ...

  9. (Delphi)第一个Windows 32 API的窗口程序

    program Project1; uses Winapi.Windows, Winapi.messages; {$R *.res} const className = 'MyDelphiWindow ...

  10. 6、OpenCV Python 图像模糊

    __author__ = "WSX" import cv2 as cv import numpy as np #均值模糊 中值模糊 自定义模糊(卷积) #卷积原理 #均值模糊 de ...