通用双向链表的设计(参考Linux系统中的实现)
通常我们设计设计链表都是将数据域放在里面,这样每次需要使用链表的时候都需要实现一个链表,然后重新实现它的相关操作,这里参考Linux系统中的设计实现了一个通用的双向链表,只需要在你的结构里面有一个这个链表的域,就可以使用链表的相关操作了。
注意:这个通用的双向链表是参考Linux系统中的实现,它使用了typeof这个功能,所以有些编译器可能不支持。我是再Windows系统中使用MinGW下使用GCC编译的。
////////////////////////////////////////////////////////////////////////////////////////
// list.h
#ifndef _list_h
#define _list_h
typedef struct _list_head {
struct _list_head *prev,*next;
} list_head;
#define offsetof(TYPE,MEMBER) ( (size_t) &((TYPE*)0)->MEMBER )
#define container_of(ptr,type,member) ({\
const typeof( ((type*)0)->member ) *__mptr = (ptr);\
(type*)( (char*)__mptr - offsetof(type,member) );})
#define list_empty(head) ( head->next==0&&head->prev==0 )
/* get the member of list object
* @ptr pointer to list_head
* @type the type of container which contains list_head field
* @memeber field name in the container
* @return return pointer to the container
*/
#define list_entry(ptr,type,member) container_of(ptr,type,member)
/* add a new node after `head`
*/
void list_add(list_head *head,list_head *node);
/* delete a node
*/
void list_del(list_head *node);
#endif
/////////////////////////////////////////////////////////
// list.c
#include "list.h"
/* add a new node after `head`
*/
void list_add(list_head *head,list_head *node) {
if(list_empty(head)) {
head->next = head;
head->prev = head;
}
node->next = head->next;
node->prev = head;
head->next->prev = node;
head->next = node;
}
/* delete a node
*/
void list_del(list_head *node) {
node->prev->next = node->next;
node->next->prev = node->prev;
}
///////////////////////////////////////////////////////////////////////////////
// test.c
#include <stdio.h>
#include <assert.h>
#include "list.h"
typedef struct _task {
int id;
list_head next;
} task;
#define task_next(t) ( container_of(t->next.next,task,next) )
void task_print(task *t) {
printf("#%d -> ",t->id);
}
void task_foreach(task *head,void (*callback)(task *)) {
task *p = head;
do {
callback(p);
p = task_next(p);
}
while (p!=head);
}
// use task like a list
void test_list() {
task t1={1,{0,0}},
t2={2,{0,0}},
t3={3,{0,0}},
t4={4,{0,0}},
t5={5,{0,0}};
list_add(&t1.next,&t2.next);
list_add(&t2.next,&t3.next);
list_add(&t3.next,&t4.next);
list_add(&t4.next,&t5.next);
task_foreach(&t1,task_print);
}
int main(int argc, char *argv[]) {
test_list();
return 0;
}
编译运行
gcc test.c list.h list.c -o test
.\test.exe
下载代码
通用双向链表的设计(参考Linux系统中的实现)的更多相关文章
- 常见linux系统中RPM包的通用命名规则
本文重点说一下在常见的linux系统中,RPM包通用的命名规则. RPM包的一般格式为:name-version-arch.rpmname-version-arch.src.rpm 例:httpd-2 ...
- (转)浅谈 Linux 系统中的 SNMP Trap
原文:https://www.ibm.com/developerworks/cn/linux/l-cn-snmp/index.html 简介 本文讲解 SNMP Trap,在介绍 Trap 概念之前, ...
- 在linux系统中安装VSCode(Visual Studio Code)
在linux系统中安装VSCode(Visual Studio Code) 1.从官网下载压缩包(话说下载下来解压就直接可以运行了咧,都不需要make) 访问Visual Studio Code官网 ...
- 用户管理 之 在Linux系统中,批量添加用户的操作流程
一.阅读此文件您需要掌握的基础知识: <Linux 用户(user)和用户组(group)管理概述><用户(user)和用户组(group)配置文件详解><Linux 用 ...
- 用户管理 之 Linux 系统中的超级权限的控制
在Linux操作系统中,root的权限是最高的,也被称为超级权限的拥有者.普通用户无法执行的操作,root用户都能完成,所以也被称之为超级管理用户. 在系统中,每个文件.目录和进程,都归属于某一个用户 ...
- 获得Unix/Linux系统中的IP、MAC地址等信息
获得Unix/Linux系统中的IP.MAC地址等信息 中高级 | 2010-07-13 16:03 | 分类:①C语言. Unix/Linux. 网络编程 ②手册 | 4,471 次阅读 ...
- 理解Linux系统中的load average(图文版)转
一.什么是load average? linux系统中的Load对当前CPU工作量的度量 (WikiPedia: the system load is a measure of the amount ...
- Linux系统中常见文件系统格式
Windows常用的分区格式有三种,分别是FAT16.FAT32.NTFS格式. 在Linux操作系统里有Ext2.Ext3.Linux swap和VFAT四种格式. FAT16: 作为一种文件名称, ...
- Linux系统中存储设备的两种表示方法
转:https://blog.csdn.net/holybin/article/details/38637381 一.对于IDE接口的硬盘的两种表示方法: 1.IDE接口硬盘,对于整块硬盘的两种表示方 ...
随机推荐
- SSH 原理和公匙私匙
先主要介绍了Telnet.SSH 的通信原理,分析了其通信时的工作流程. Telnet 无论Telnet协议连接的是什么类型终端,都会转换为NVT(Net Virtual Terminal)格式进行通 ...
- app后端开发系列文章文件夹
一点废话 每个程序猿心中,都有一个大牛梦.我们在晨曦之光中敲击着代码,在寒冬覆雪中思考着0与1. 夏练三伏 冬练三九这说的就是我们这群[江湖]中人.在这里我们门派林立,C语言派历史悠久,在程序界就是嵩 ...
- 2016 第七届蓝桥杯 c/c++ B组省赛真题及解题报告
2016 第七届蓝桥杯 c/c++ B组省赛真题及解题报告 勘误1:第6题第4个 if最后一个条件粗心写错了,答案应为1580. 条件应为abs(a[3]-a[7])!=1,宝宝心理苦啊.!感谢zzh ...
- TI C66x DSP 四种内存保护问题 -之- CPU訪问corePac内部资源时的内存保护问题
CPU訪问corePac内部资源(L1.L2)时的内存保护(通过设置内存的訪问权限实现)等问题请參考以下两个blog.已经叙述的非常具体. "TI C66x DSP 系统events及其应用 ...
- 千呼万唤始出来:ArchLinux for Espressobin
前言 原创文章,转载引用务必注明链接,水平有限,如有疏漏,欢迎指正. 本文使用Markdown写成,为获得更好的阅读体验和正常的链接.图片显示,请访问我的博客原文: http://www.cnblog ...
- shell-判断循环
shell条件测试 test 每个完整的合理的编程语言都具有条件判断的功能. bash可以使用test命令,[]和()操作,还有if/then结构 字符串判断 -n string 判断字符串长度非零 ...
- 服务管理-DNS
DNS服务 DNS(Domain Names System,域名系统),因特网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP地址.通 ...
- undefined reference to libiconv_open ext/iconv/.libs/iconv.o by install phpsource
错误信息:ext/iconv/.libs/iconv.o(.text+0x30e2): In function `php_iconv_stream_filter_factory_create':/ho ...
- NYOJ 905 卡片游戏
卡片游戏 时间限制:1000 ms | 内存限制:65535 KB 难度:1 描写叙述 小明近期宅在家里无聊.于是他发明了一种有趣的游戏.游戏道具是N张叠在一起的卡片,每张卡片上都有一个数字,数字 ...
- JAVA学习之路与大家分享
这是我四年以前总结的JAVA学习之路,希望对初学者或想从事JAVA开发的人有帮助. 本人是软件工程专业出身,先后学过C.C++.JAVA.VB.delphi等等开发语言以及网络相关管理技术.哎,好久不 ...