Linux下一个实用的头文件

大家好,我是linuxzn。
本次分享sys/queue.h:
什么是sys/queue.h?
queue.h是linux、freebsd中的一个头文件。
freebsd:freebsd 是一种类 unix操作系统。
这是一个很实用的头文件,因为这个头文件里全是宏定义操作,所以其不仅可以使用在linux/嵌入式linux项目中,也可以使用在单片机项目中,我也是因为在我们的单片机项目中看到,才知道有这么一个头文件的。我觉得挺实用的,与大家分享。
它使用宏实现了如下数据结构:
slist:单向无尾链表
list:双向无尾链表
stailq:单向有尾链表(可作队列使用)
tailq:双向有尾链表(可作队列使用)
所有的数据结构都支持如下功能:
在链表头插入节点
在任意节点后插入节点
删除节点
遍历节点
我们可以在linux系统的如下路径中找到这个头文件:
/usr/include/sys/queue.h
也可以通过如下网址查看:
https://code.woboq.org/userspace/glibc/misc/sys/queue.h.html
sys/queue.h的使用
下面我们基于slist来演示其使用。
slist相关宏定义:
/* * singly-linked list definitions. */#define slist_head(name, type)         struct name {                    struct type *slh_first; /* first element */        }#define slist_head_initializer(head)        { null }#define slist_entry(type)          struct {               struct type *sle_next; /* next element */     }/* * singly-linked list functions. */#define slist_init(head) do {          (head)->slh_first = null;         } while (/*constcond*/0)#define slist_insert_after(slistelm, elm, field) do {    (elm)->field.sle_next = (slistelm)->field.sle_next;    (slistelm)->field.sle_next = (elm);       } while (/*constcond*/0)#define slist_insert_head(head, elm, field) do {     (elm)->field.sle_next = (head)->slh_first;      (head)->slh_first = (elm);         } while (/*constcond*/0)#define slist_remove_head(head, field) do {       (head)->slh_first = (head)->slh_first->field.sle_next;  } while (/*constcond*/0)#define slist_remove(head, elm, type, field) do {     if ((head)->slh_first == (elm)) {         slist_remove_head((head), field);       }                else {                struct type *curelm = (head)->slh_first;      while(curelm->field.sle_next != (elm))        curelm = curelm->field.sle_next;       curelm->field.sle_next =              curelm->field.sle_next->field.sle_next;     }               } while (/*constcond*/0)#define slist_foreach(var, head, field)        for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)/* * singly-linked list access methods. */#define slist_empty(head) ((head)->slh_first == null)#define slist_first(head) ((head)->slh_first)#define slist_next(elm, field) ((elm)->field.sle_next)  
下面我们通过实例来操作。
首先,创建链表头节点、其它节点结构体,用到slist_head与slist_entry这两个宏定义:
#define elem_type int/* 链表节点 */typedef struct node {    elem_type data;    slist_entry(node) field; }node_st;/* 链表头 */typedef slist_head(head, node) head_st;  
链表数据域类型我们定义为int,field表示的是指针域。
① 创建一个头结点:
/* 创建链表头节点并初始化 */head_st *head = (head_st *)malloc(sizeof(head_st));slist_init(head);  
头节点:不存任何数据的空节点,通常作为链表的第一个节点。
② 在链表头部分别插入节点node1、node2:
/* 头插法插入一个节点node1 */node_st *node1 = (node_st *)malloc(sizeof(node_st));node1->data = 1;slist_insert_head(head, node1, field);/* 头插法插入一个节点node2 */node_st *node2 = (node_st *)malloc(sizeof(node_st));node2->data = 2;slist_insert_head(head, node2, field);  
头指针:永远指向链表第一个节点的位置。
slist_insert_head是从链表头部插入节点,新节点总是从头结点之后插入。
③ 在链表节点node2之后插入节点node3:
node_st *node3 = (node_st *)malloc(sizeof(node_st));node3->data = 3;slist_insert_after(node2, node3, field);  
slist_insert_after是从指定节点slistelm之后插入新节点elm。
④ 遍历链表:
node_st *tmp_elm;slist_foreach(tmp_elm, head, field){ printf(%d , tmp_elm->data);}  
输出为tmp_elm,访问tmp_elm即可。
⑤ 删除某个节点node2
slist_remove(head, node2, node, field);free(node2);node2 = null;  
⑥ 销毁整个链表
while (!slist_empty(head)) {        node_st *p = slist_first(head);    slist_remove_head(head, field);    free(p);    p = null;}free(head);head = null;  
完整测试代码:
#include #include #include #define elem_type int/* 链表节点 */typedef struct node {    elem_type data;    slist_entry(node) field; }node_st;/* 链表头 */typedef slist_head(head, node) head_st;int main(void){    /* 创建链表头节点并初始化 */    head_st *head = (head_st *)malloc(sizeof(head_st));    slist_init(head);    /* 头插法插入一个节点node1 */    node_st *node1 = (node_st *)malloc(sizeof(node_st));    node1->data = 1;    slist_insert_head(head, node1, field);    /* 头插法插入一个节点node2 */    node_st *node2 = (node_st *)malloc(sizeof(node_st));    node2->data = 2;    slist_insert_head(head, node2, field);    /* 遍历打印当前链表节点 */    printf(list:);    node_st *tmp_elm;    slist_foreach(tmp_elm, head, field)    {        printf(%d , tmp_elm->data);    }    printf();    /* 尾插法插入一个节点node3 */    printf(insert node3:);    node_st *node3 = (node_st *)malloc(sizeof(node_st));    node3->data = 3;    slist_insert_after(node2, node3, field);    slist_foreach(tmp_elm, head, field)    {        printf(%d , tmp_elm->data);    }    printf();    /* 删除node2 */    printf(delete node2:);    slist_remove(head, node2, node, field);    free(node2);    node2 = null;    slist_foreach(tmp_elm, head, field)    {        printf(%d , tmp_elm->data);    }    printf();    /* 销毁链表 */    while (!slist_empty(head))     {            node_st *p = slist_first(head);        slist_remove_head(head, field);        free(p);        p = null;    }    free(head);    head = null;    return 0;}  
编译、运行:
运行结果与我们上面分析的一致。
本次我们只分享queue.h里最简单的数据结构。其它几种数据结构的使用例子及相关宏说明可以通过man命令查看。
man是linux下的帮助命令。
我们输入 man queue 即可查到queue.h的相关说明:
可以看到,man命令很强大,可查到queue的帮助说明很详细,有宏的说明及使用示例等。
以上就是本次的分享,文章如有错误,欢迎支持,谢谢!我们下期见~


触发器的基本原理、应用场景及优缺点
Zenoah Engines G380PU飞机发动机
用电设备组的计算负荷
人工智能语音鉴黄,高科技助力净化网络环境
压电陶瓷致动器的工作原理
Linux下一个实用的头文件
深圳大学利用光参量放大技术创造了高空间分辨率成像的新记录
格力迎大批新生入职!董明珠金句频出,引爆全场
英伟达与软银达成协议,将以400亿美元收购ARM
2018年,东芝家电业务扭亏为盈
Diodes 推出2款车规格降压LED驱动器 适用于驱动汽车内外部LED照明
RK3399开源主板-性能达到intel凌动级别
iphone8要在手机侧面跟背面“做文章”?
区块链项目需要避免的常见错误和解决方法
新能源车电池迎来“退役潮”20万吨电池怎么处理?
如何选取最合适的音频放大器
串扰学习笔记(1)
国外IC前缀索引-4(S-T)
光纤通信及电力传输企业中天科技发布2022第一季度报告
嵌入式是做什么的_嵌入式开发具体做什么