首页 > 解决方案 > Linked List 功能解释,结构体指针的订阅

问题描述

在 C 中编写一个简单的单链表,我在 Github 上找到了这个存储库:https ://github.com/clehner/ll.c ,同时寻找一些示例。
有以下函数(_list_next(void *)):

struct list 
{
    struct list *next;      // on 64-bit-systems, we have 8 bytes here, on 32-bit-systems 4 bytes.
    void *value[];          // ISO C99 flexible array member, incomplete type, sizeof may not be applied and evaluates to zero.
};

void *_list_next(void *list)
{
    return list ? ((struct list *)list)[-1].next : NULL;   // <-- what is happening here?
}

你能解释一下这是如何工作的吗?
看起来他正在将一个 void 指针转换为一个列表指针,然后下标该指针。这是如何工作的,那里到底发生了什么?
我不明白[-1].

标签: clinked-listsingly-linked-list

解决方案


这是在作者尝试过的系统上发生的未定义行为。

要了解发生了什么,请注意 的返回值_ll_new

void * _ll_new(void *next, size_t size)
{
    struct ll *ll = malloc(sizeof(struct ll) + size);
    if (!ll)
        return NULL;
    ll->next = next;
    return &ll->value;
}

作者给你的是 的地址value,不是节点的地址。但是,_list_next需要 : 的地址,struct list否则无法访问next。因此,为了找到next会员,您需要通过返回一名会员来找到其地址。

list这就是索引at背后的想法[-1]- 它获取与 的next特定地址相关联的地址value。但是,这会将数组索引到其有效范围之外,这是未定义的行为。

其他函数也这样做,但它们使用指针算法而不是索引。例如,_ll_pop使用

ll--;

达到相同的结果。

更好的方法是使用类似于container_ofmacro的东西。


推荐阅读