该楼层疑似违规已被系统折叠 隐藏此楼查看此楼

链表是我们学习C语言避不开的问题,就让我们一起飞过去看看吧:

1 定义链表

链表是C语言编程中常用的数据结构,比如我们要建一个整数链表,一般可能这么定义:

struct int_node {

int val;

struct int_node *next;

};

2 定义功能函数

为了实现链表的插入、删除、遍历等功能,另外要再实现一系列函数,比如:

void insert_node(struct int_node **head, int val);

void delete_node(struct int_node *head, struct int_node *current);

void access_node(struct int_node *head){

struct int_node *node;

for (node = head; node != NULL; node = node->next)

{

// do something here

}

}

如果我们的代码里只有这么一个数据结构的话,这样做当然没有问题,但是当代码的规模足够大,需要管理很多种链表,难道需要为每一种链表都要实现一套插入、删除、遍历等功能函数吗?

熟悉C++的同学可能会说,我们可以用标准模板库啊,但是,我们这里谈的是C,在C语言里有没有比较好的方法呢?

Linux内核中一般使用双向链表,声明为struct list_head,这个结构体是在include/linux/types.h中定义的,链表的访问是以宏或者内联函数的形式在include/linux/list.h中定义。

struct list_head { struct list_head *next, *prev;};

Linux内核为链表提供了一致的访问接口。

void INIT_LIST_HEAD(struct list_head *list);

void list_add(struct list_head *new, struct list_head *head);

void list_add_tail(struct list_head *new, struct list_head *head);

void list_del(struct list_head *entry);

int list_empty(const struct list_head *head);

以上只是从Linux内核里摘选的几个常用接口,更多的定义请参考Linux内核源代码。

3 处理链表

我们先通过一个简单的实作来对Linux内核如何处理链表建立一个感性的认识。

#include

#include "list.h" struct int_node

{

int val;

struct list_head list;

};

int main()

{

struct list_head head, *plist;

struct int_node a, b;

a.val = 2;

b.val = 3;

INIT_LIST_HEAD(&head);

list_add(&a.list, &head);

list_add(&b.list, &head);

list_for_each(plist, &head) {

struct int_node *node = list_entry(plist, struct int_node, list);

printf("val = %d\n", node->val);

}

return 0;

}

看完这个实作,是不是觉得在C代码里管理一个链表也很简单呢?

代码中包含的头文件list.h是我从Linux内核里抽取出来并做了一点修改的链表处理代码,现附在这里给大家参考,使用的时候只要把这个头文件包含到自己的工程里即可。

4 代码

list_head通常是嵌在数据结构内使用,在上文的实作中我们还是以整数链表为例,int_node的定义如下:

struct int_node {

int val;

struct list_head list;

};

使用list_head组织的链表的结构如下图所示:

遍历链表是用宏list_for_each来完成。

#define list_for_each(pos, head)

for (pos = (head)->next; prefetch(pos->next), pos != (head);

pos = pos->next)

在这里,pos和head均是struct list_head。在遍历的过程中如果需要访问节点,可以用list_entry来取得这个节点的基址。

#define list_entry(ptr, type, member)

\ container_of(ptr, type, member)

我们来看看container_of是如何实现的。如下图所示,我们已经知道TYPE结构中MEMBER的地址,如果要得到这个结构体的地址,只需要知道MEMBER在结构体中的偏移量就可以了。如何得到这个偏移量地址呢?这里用到C语言的一个小技巧,我们不妨把结构体投影到地址为0的地方,那么成员的绝对地址就是偏移量。得到偏移量之后,再根据ptr指针指向的地址,就可以很容易的计算出结构体的地址。

list_entry就是通过上面的方法从ptr指针得到我们需要的type结构体。

现在我们就从菜鸟变成不那么菜的鸟了_,当然,如果还有疑问的小伙伴可以直接联系我,也可以加群710520381,柳猫,跟你们不见不散……

c语言新建一个单向链表菜鸟,【图片】菜鸟的进击——玩转C语言链表【c程序设计吧】_百度贴吧...相关推荐

  1. c语言链表萌新,菜鸟的进击——玩转C语言链表

    链表是我们学习C语言避不开的问题,就让我们一起飞过去看看吧: 1 定义链表 链表是C语言编程中常用的数据结构,比如我们要建一个整数链表,一般可能这么定义: struct int_node { int ...

  2. 用c语言程序画圣诞树,【图片】用C语言画一棵“圣诞树”(前方高能,学渣小心避让!)【广西科技大学吧】_百度贴吧...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 #include #include #include #define PI 3.14159265359 float sx, sy; float sdCir ...

  3. python单链表逆序_C语言实现一个单向链表,并写程序把单向链表进行逆序?

    上图是题目需要实现的效果. 纯小白才开始学C语言,求指导,只输出了0到9,不知如何逆序输出. 中间重复的代码部分应该是要优化一下的,但暂时还不知到该怎么写. #import typedef struc ...

  4. LISP 圆孔标记_在AUTOCAD中如何用lisp语言新建一个标注样式

    标注样式要先建立字体样式.62616964757a686964616fe78988e69d8331333337616533 如果箭头没有块的话,要建立块. ;;;主程序标注样式 (defun Text ...

  5. C语言写一个猜数字游戏?我只想玩王者荣耀

    #include <stdio.h> #include <time.h> #include <stdlib.h> //先构造函数 //1.菜单 2.游戏实现函数 3 ...

  6. c语言编写一个字母金字塔,【强迫症满足向】字母金字塔: C语言实现

    本质是for循环练习,金字塔在文后 一.初级阶段:输出菱形星星 这是一个for循环小练习 为满足强迫症需求, Leo先放个图爽一爽 算法本身不难, 注意循环结束条件, 初值的设置, 利用等差公式等等 ...

  7. c语言写一个进出货管理,[源码和文档分享]基于C语言实现的超市管理系统

    1 需求分析 超市随着市场经济和现代信息技术的的发展,不可必要的要卷入信息现代化的大潮,如何使用现代化的工具,使企业和经营者个人在最小的投入下获取最大的回报,成为每一个人的梦想.因此,在超市管理中引进 ...

  8. can帧格式 dlc_【图片】CAN扩展帧结构【汽车can总线吧】_百度贴吧

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 1. 帧起始(Start of Frame) 标志数据帧(包含远程帧),它由一个显性位(0)构成,只有在总县处于空闲状态时,才允许开始发送.所有节点必须同 ...

  9. 商品分类列表功能实现php,【图片】B2B2C系统如何实现商品分类功能【thinkphp吧】_百度贴吧...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 B2B2C系统如何实现商品分类功能 需要完成一个独立的B2B2C系统,系统分类和店铺商品分类是必不可少的.让我们看看商品分类是什么:商品分类是概括一定范围 ...

最新文章

  1. s-sed(stream editor) 文本填充和编辑 基本使用
  2. python3.7安装教程linux_linux系统安装Python 3.7.x
  3. windbg检测句柄泄露(定位到具体代码)
  4. VIO-slam 系统构建
  5. C语言可变参数只会用算啥本事?看我来抽丝剥茧干翻它!
  6. appium GUI介绍
  7. server2008安装iis php,window server 2008 iis7+php安装配置
  8. Delphi拖放编程
  9. 程序员如何用“撞针“拯救 35 亿地球人?
  10. 数据结构基础学习(一)数组
  11. Reverse Linked List II -- LeetCode
  12. shell脚本 把一个文件的内容全部转换为大写
  13. 炒菜多放油:确实好吃,可是又不健康
  14. 神经网络 神经元_神经去耦
  15. 让面试官赞扬的IO读取方法:大文件进行词频统计(单线程与多线程分别解决)利用Buffer流简单又快捷
  16. groupmod 修改用户组信息
  17. python汇率换算注释_【菜鸟学Python】案例一:汇率换算
  18. Selenium中的EC模块
  19. BP神经网络实现异或功能
  20. linux系统怎么改回win7系统,linux系统怎么安装win7系统?

热门文章

  1. Daily Scrum: 2012/11/27
  2. VC++程序设计与应用--图形和文本输出
  3. 数据库性能优化八大方案,你知道几个
  4. dbn源代码matlab,深度学习工具箱的DBN代码的例子有问题
  5. 【离散数学】证明:超人不存在
  6. 运维面试中提到的熔断和降级
  7. 双层神经网络实现非线性回归——机器学习
  8. Android camera2判断设备是否有相机功能,获取摄像头数量
  9. 最小堆(MinHeap)
  10. 2021年中国研究生数学建模竞赛F题——航空公司机组优化排班问题