zoukankan      html  css  js  c++  java
  • 链表的新写法

    链表的新奇写法

    我以前写链表的时候总是习惯这样写:

    struct Example {
        int e;
        double d;
    };
    
    struct list_node {
        struct list_node* prev;
        struct Example* data;
        struct list_node* next;
    };
    

    不知道有没有人和我一样。这种方式写链表,我们可以根据链表头很快找到某个data,但是无法根据一个data 找到这个链表。

    但是最近发现了另一种方式写链表,可以使得两种被双向找到。

    struct Example {
        int e;
        double d;
        struct list_node* list;
    };
    
    struct list_node {
        struct list_node* prev;
        struct list_node* next;
    };
    

    显然,要根据一个 struct Example 找到整条链表是非常容易的。那要怎么根据一个链表结点找到其所属的 struct Example 呢?

    答案是根据结构体内的各个成员的偏移量,我们知道一个链表结点的地址 node ,那么只要用这个地址减去其在结构体内的偏移量不就是 struct Example 的地址了吗?

    因此我们可以定义一个宏函数:

    #include <stddef.h>
    #define CONTAINER_OF(ptr, type, member)
        ((type*)((char*)ptr - offsetof(type, member)))
    

    这个宏函数的三个参数分别表示链表结点的指针,相应的要找到的结构体类型,这里是 struct Example,以及链表结点在该结构体中的名字。

    offsetof 同样是一个宏函数,其返回一个 type 的成员变量 member 在其内的偏移量。

    通过这个宏函数,我们就可以这样找到相应的结构体了:

    struct list_node* node;
    struct Example* e = CONTAINER_OF(node, struct Example, list);
    

    这样虽然并不能节省空间,但是链表与其对应的结构体绑定更加紧密了。我看到很多开源项目如果有链表的话都倾向于这种写法,说明还是有其优势的。

  • 相关阅读:
    koa 基础(十)原生node.js 在 koa 中获取表单提交的数据
    koa 基础(九) ejs 模板引擎的使用
    koa 基础(八)koa 中间件的执行顺序
    koa 基础(七)错误处理中间件
    [翻译] KVNProgress
    编写带有点击特效的UIButton
    用Easing函数实现碰撞效果
    EasingAnimation
    什么时候会执行viewDidLoad方法
    UIButton的两种block传值方式
  • 原文地址:https://www.cnblogs.com/lunar-ubuntu/p/13956182.html
Copyright © 2011-2022 走看看