2

Berkeley 在他们的 FreeBSD 中实现的queue.h确实非常有用,现在我有一个关于TAILQ_LAST宏的问题,请注意我提出的不同之处

原始代码

#define    TAILQ_HEAD(name, type)                        \
struct name 
{                                \
    struct type *tqh_first;    /* first element */            \
    struct type **tqh_last;    /* addr of last next element */        \
}

#define    TAILQ_ENTRY(type)                        \
struct 
{                                \
   struct type *tqe_next;    /* next element */            \
   struct type **tqe_prev;    /* address of previous next element */    \
}

#define    TAILQ_LAST(head, headname)                    \
(*(((struct headname *)((head)->tqh_last))->tqh_last))

我的提议

#define    TAILQ_LAST(head, headname)                    \
((head)->tqh_last))

我的观点是 headname 的tqh_last成员是指最后一个TAILQ_ENTRY的tqe_next成员的地址,这正是tailq中最后一个条目的地址。

如果我错了,请纠正我。提前致谢。

4

2 回答 2

1

只看这两个定义,我认为

#define    TAILQ_LAST(head, headname)                    \
(*(((struct headname *)((head)->tqh_last))->tqh_last))

将返回一个type*而这

#define    TAILQ_LAST(head, headname)                    \
((head)->tqh_last))

将返回 a type**,因此两者不等价。

于 2012-11-17T16:05:59.213 回答
0

不,它们不一样。请注意,tqh_last 是最后一个元素的地址,而不是最后一个元素。如果您直接使用(head)->tqh_last,那么它只会返回 NULL。

那为什么会这样*(((struct headname *)((head)->tqh_last))->tqh_last)

请看:

    #define TAILQ_INSERT_TAIL(head, elm, field) do {            \
    TAILQ_NEXT((elm), field) = NULL;                \
    (elm)->field.tqe_prev = (head)->tqh_last;           \
    *(head)->tqh_last = (elm);                  \
    (head)->tqh_last = &TAILQ_NEXT((elm), field);           \
} while (0)

(head)->tqh_last = &TAILQ_NEXT((elm), field); 我们需要的是&TAILQ_NEXT((elm), field)->field.tqe_prev,根据(elm)->field.tqe_prev = (head)->tqh_last;,然后我们得到 (*(((struct headname *)((head)->tqh_last))->tqh_last))

于 2019-07-26T08:43:13.543 回答