Я просто изучаю указатели void и двойные указатели в C и тому подобное, чтобы попытаться сделать вещи динамичными. Затем я наткнулся на это, которое выглядит как следует:
typedef void *QUEUE[2];
#define QUEUE_NEXT(q) (*(QUEUE **) &((*(q))[0]))
#define QUEUE_PREV(q) (*(QUEUE **) &((*(q))[1]))
Для моих глаз происходит слишком много указателей, скобок и ссылок. Интересно, может ли кто-нибудь объяснить:
- что делает этот раздел
(*(QUEUE **) &((*(q))
, и - как эта очередь может иметь только два элемента.
Как это работает? В частности, у них есть это:
#define QUEUE_INSERT_TAIL(h, q) \
do { \
QUEUE_NEXT(q) = (h); \
QUEUE_PREV(q) = QUEUE_PREV(h); \
QUEUE_PREV_NEXT(q) = (q); \
QUEUE_PREV(h) = (q); \
} \
while (0)
Как это QUEUE_INSERT_TAIL
работает?
Или, например, мне также было бы интересно узнать, что происходит с этим:
#define QUEUE_INIT(q) \
do { \
QUEUE_NEXT(q) = (q); \
QUEUE_PREV(q) = (q); \
} \
while (0)
...
QUEUE_INIT(&loop->wq);
QUEUE_INIT(&loop->idle_handles);
QUEUE_INIT(&loop->async_handles);
QUEUE_INIT(&loop->check_handles);
QUEUE_INIT(&loop->prepare_handles);
QUEUE_INIT(&loop->handle_queue);
В конце концов, все они используют QUEUE_NEXT
и QUEUE_PREV
внутри, творя какую-то магию.
QUEUE
, который используется для связывания элементов в циклическую двусвязную цепочку. МакросQUEUE_DATA
используется для доступа к исходной структуре из указателя на ее элементQUEUE
. - person Tom Karzes   schedule 11.04.2020