`
yuanlanjun
  • 浏览: 1184221 次
文章分类
社区版块
存档分类
最新评论

嵌入式C语言那点事(三)Linux中霸道的双向链表源码与应用

 
阅读更多

C语言作为面向过程的语言,想写出灵活的结构与封装需要很高技巧。

但由于C语言的高效,几乎所有操作系统和面向对象语言的最底层实现都使用了C语言。即,使用C完成面向对象的封装。

这次通过整理与仿写Linux的双向链表让我体会到了一些C语言封装的核心技巧。

这个双向链表的巧妙之处在于1)利用宏将“函数”入参扩展出了“结构类型”; 2)利用纯地址偏移获取结构体指针;

下面是具体实现:链表的实现由于是宏定义,都在libList.h中。

测试程序testList.c与testList.h。


libList.h

#ifndef _LIBLIST_H
#define _LIBLIST_H

#ifdef __cplusplus
extern "C" {
#endif

/* 链表头节点定义 */
typedef struct tagstList_Head {
	struct tagstList_Head *next, *prev;
}stList_Head;

/* 初始化双向链表 */
#define list_init(head) do			\
{						\
	(head)->next = (head)->prev = (head);	\
} while(0)

/* 在指定元素(where)之后插入新元素(item) */
#define list_add(item, towhere) do	\
{					\
	(item)->next = (towhere)->next;	\
	(item)->prev = (towhere);	\
	(towhere)->next = (item);	\
	(item)->next->prev = (item);	\
} while(0)

/* 在指定元素(where)之前插入新元素(item) */
#define list_add_before(item, towhere)  \
	list_add(item,(towhere)->prev)

/* 删除某个元素 */
#define list_remove(item) do			\
{						\
	(item)->prev->next = (item)->next;	\
	(item)->next->prev = (item)->prev;	\
} while(0)

/* 正向遍历链表中所有元素 */
#define list_for_each_item(item, head)\
	for ((item) = (head)->next; (item) != (head); (item) = (item)->next)

/* 反向遍历链表中所有元素 */
#define list_for_each_item_rev(item, head) \
	for ((item) = (head)->prev; (item) != (head); (item) = (item)->prev)

/* 根据本节点(item)获取节点所在结构体(type)的地址 */
/* 节点item地址(member的地址) - 该链表元素member在结构体中的偏移 */
#define list_entry(item, type, member) \
	((type *)((char *)item - (char *)(&((type *)0)->member)))

/* 判断链表是否为空 */
#define list_is_empty(head)	\
	((head)->next == (head))

/* 获取指定位置上一元素 */
#define list_prev_item(item)\
	((head)->prev)

#ifdef __cplusplus
}
#endif

#endif


testList.h

#ifndef _TESTLIST_H
#define _TESTLIST_H

#ifdef __cplusplus
extern "C" {
#endif

#include "libList.h"

typedef struct tagInteger
{
	int idx;
	stList_Head	stListHead;
}stInteger;

extern void testlist();

#ifdef __cplusplus
}
#endif

#endif

这种双向链表的特点在于:在需要链表管理的结构中定义一个链表节点变量,然后所有的操作都是针对这个链表节点进行的。在需要获取该结构时使用list_entry即可。


testList.c

#ifdef __cplusplus
extern "C" {
#endif

#include <malloc.h>
#include <stddef.h>
#include "stdafx.h"
#include "testList.h"

void testlist()
{
	int i = 0;
	stList_Head		stListHead;
	stList_Head		*pstListHead= NULL;

	stInteger		*pstInteger	= NULL;
	stList_Head		*pstTmpList	= NULL;

	/* 链表初始化 */
	pstListHead = &stListHead;
	list_init(pstListHead);

	/* 生成节点并挂入链表 */
	for(i = 0; i < 32; i++)
	{
		pstInteger = (stInteger *)malloc(sizeof(stInteger));
		if (NULL == pstInteger)
		{
			printf("pstInteger malloc fail!");
			return;
		}
		pstInteger->idx = 100 - i;

		/* 挂到头结点之前 */
		list_add_before(&pstInteger->stListHead, pstListHead);

		/* 挂到头结点之后 */
		//list_add(&pstInteger->stListHead, pstListHead);
	}
	
	/* 正向遍历链表中每一个元素并输出 */
	list_for_each_item(pstTmpList, pstListHead)
	{
		if(NULL != pstTmpList)
		{
			pstInteger = list_entry(pstTmpList, stInteger, stListHead);
			printf("%d ",pstInteger->idx);
		}
	}
	
	return;

}

#ifdef __cplusplus
{
#endif



分享到:
评论

相关推荐

    嵌入式Linux C编程入门(第2版) PPT

    第6章 嵌入式linux c语言基础——数组、指针与结构 168 6.1 数组 169 6.1.1 一维数组 169 6.1.2 字符串 172 6.1.3 二维数组 174 6.2 指针 175 6.2.1 指针的概念 175 6.2.2 指针变量的操作 ...

    嵌入式高级C语言进阶-第五讲 数据结构与链表

    这是东南大学集成电路研究中心凌明老师的嵌入式高级C语言开发的课件,源码我一并上传

    嵌入式自助点餐平板电脑是以餐饮业为平台,嵌入式Linux技术、网络通信技术作为本项目的支撑+源代码+文档说明

    #### 用户点单功能实现了菜品动态添加的功能,通过将菜品信息以及菜品图片名称写入food.txt文件,应用菜品链表,实现菜单的动态更新。同时实现了菜单左右滑动翻页,单击菜品加一,长按菜品加一,左侧动态显示用户...

    基于ARM的电子相册源码(含动态库可运行)

    解压执行make可编译,基于ARM平台的电子相册实现源码,含带jpeg和freetype动态库,代码涉及大量指针操作、大量链表操作、framebuffer屏显、目录/文件检测、字体编解码、图片编解码操作,Makefile文件也可做其他...

    Visual C++音频视频处理技术及工程实践(含源码2/2)

    采用的案例均来源于作者实际开发工作,具有很好的实用价值,可以帮助读者在开发中进行参考或直接应用。 第1篇 开发基础 1 第1章 数字音视频开发技术基础 3 1.1 数字音视频基本概念 4 1.1.1 数字音频技术基础 4 ...

    若干源程序资料12.rar

    2012-06-11 21:44 6,947,979 Linux内核完全注释V3.0书签版(带源码).rar 2012-06-11 21:31 11,599 MATLAB仿真程序OFDM程序.txt 2012-06-11 21:37 14,584,477 msdn for vb6.0简体中文版.zip 2012-06-11 21:02 12,288 ...

    Visual C++音频视频处理技术及工程实践(分卷0)

    采用的案例均来源于作者实际开发工作,具有很好的实用价值,可以帮助读者在开发中进行参考或直接应用。 第1篇 开发基础 1 第1章 数字音视频开发技术基础 3 1.1 数字音视频基本概念 4 1.1.1 数字音频技术基础 4 1.1.2...

    Visual C++音频/视频处理技术及工程实践 (分卷1)

    采用的案例均来源于作者实际开发工作,具有很好的实用价值,可以帮助读者在开发中进行参考或直接应用。 第1篇 开发基础 1 第1章 数字音视频开发技术基础 3 1.1 数字音视频基本概念 4 1.1.1 数字音频技术基础 4 1.1.2...

    Visual C++ 音频/视频 处理技术及工程实践(分卷3)

    采用的案例均来源于作者实际开发工作,具有很好的实用价值,可以帮助读者在开发中进行参考或直接应用。 第1篇 开发基础 1 第1章 数字音视频开发技术基础 3 1.1 数字音视频基本概念 4 1.1.1 数字音频技术基础 4 1.1.2...

    Visual C++音频视频处理技术及工程实践(分卷9)

    采用的案例均来源于作者实际开发工作,具有很好的实用价值,可以帮助读者在开发中进行参考或直接应用。 第1篇 开发基础 1 第1章 数字音视频开发技术基础 3 1.1 数字音视频基本概念 4 1.1.1 数字音频技术基础 4 1.1.2...

    Visual C++音频/视频处理技术及工程实践(分卷2)

    采用的案例均来源于作者实际开发工作,具有很好的实用价值,可以帮助读者在开发中进行参考或直接应用。 第1篇 开发基础 1 第1章 数字音视频开发技术基础 3 1.1 数字音视频基本概念 4 1.1.1 数字音频技术基础 4 1.1.2...

    Visual C++音频视频处理技术及工程实践(分卷7)

    采用的案例均来源于作者实际开发工作,具有很好的实用价值,可以帮助读者在开发中进行参考或直接应用。 第1篇 开发基础 1 第1章 数字音视频开发技术基础 3 1.1 数字音视频基本概念 4 1.1.1 数字音频技术基础 4 1.1.2...

    Visual C++音频视频处理技术及工程实践(分卷6)

    采用的案例均来源于作者实际开发工作,具有很好的实用价值,可以帮助读者在开发中进行参考或直接应用。 第1篇 开发基础 1 第1章 数字音视频开发技术基础 3 1.1 数字音视频基本概念 4 1.1.1 数字音频技术基础 4 1.1.2...

    Visual C++音频视频处理技术及工程实践地址

    采用的案例均来源于作者实际开发工作,具有很好的实用价值,可以帮助读者在开发中进行参考或直接应用。 第1篇 开发基础 1 第1章 数字音视频开发技术基础 3 1.1 数字音视频基本概念 4 1.1.1 数字音频技术基础 4 ...

Global site tag (gtag.js) - Google Analytics