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.
的方法
在 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.