我目前正在研究C语言中宏的使用。 为了适应和学习它们,我正在研究queue.h库,该库允许在C语言中创建动态数据结构。
您可以在此处找到源: bxr.su/OpenBSD/sys/sys/queue.h
现在我偶然发现了以下定义:
#define SLIST_ENTRY(type) \
struct { \
struct type *slh_next;
}
如果我没记错的话,这会创建一个带有指针的结构,该指针将指向单链接列表中的下一个元素。 我只是不知道为什么要创建该结构。仅仅指针还不够吗?
#define SLIST_ENTRY(type) \
struct type *slh_next
我想如果您想创建一个双向链接列表,则可以使用next和before指针创建一个结构。那么,这仅仅是为了保持一致,还是SLIST定义中的结构用于特定目的?
PS:如何在手机上格式化代码和链接?
答案 0 :(得分:1)
在单个链接列表中使用它可能没有多大意义,但是如果您在source code中看到(双链接)列表的定义,那么它的用途就更加清楚了,因为现在它具有两个指针,您只需向数据结构添加一个LIST_ENTRY
结构即可。
#define LIST_ENTRY(type) \
struct { \
struct type *le_next; /* next element */ \
struct type **le_prev; /* address of previous next element */ \
}
LIST_ENTRY(type)
扩展为匿名struct
。在C11标准中,引入了匿名struct
和匿名union
。当匿名struct
或匿名union
包含在另一个struct
或union
中时,封闭结构将获取封闭的匿名结构的字段。
看看这个question和example code:
struct entry {
...
LIST_ENTRY(entry) entries;
...
} *n1, *n2, *np;
在这种情况下,LIST_ENTRY(entry)
的字段成为entry
的字段。是的,就像上面提到的那样,它是一种通用类型的链接。现在,一个函数可以从该结构中获取上一个和下一个元素,如下所示:
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
(listelm)->field.le_next->field.le_prev = \
&(elm)->field.le_next; \
(listelm)->field.le_next = (elm); \
(elm)->field.le_prev = &(listelm)->field.le_next; \
} while (0)