Linked List函数解释,结构指针的订阅

Linked List function explanation, subscription of a structure pointer

在 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] 的目的。

这是未定义的行为,恰好在作者尝试过的系统上有效。

要了解发生了什么,请记下 _ll_new 的 return 值:

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 成员,您需要向回走一位成员才能找到它的地址。

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

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

ll--;

结果相同。

更好的方法是使用类似 container_of macro.

的方法