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

2つの定義を見るだけで、

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

type*これに対してa を返します

#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 に答える