在queue.h库中使用结构

时间:2018-08-03 09:43:32

标签: c macros queue

我目前正在研究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:如何在手机上格式化代码和链接?

1 个答案:

答案 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包含在另一个structunion中时,封闭结构将获取​​封闭的匿名结构的字段。

看看这个questionexample 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)