c语言 - libuv 中的 (*(QUEUE **) &((*(q)))[0])) 是什么意思,或者队列如何工作?



我只是在 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_NEXTQUEUE_PREV,做某种魔法。

它是循环链表的接口。解决第一个宏用法时,您将获得:

  • QUEUE_NEXT(&loop->wq)->
  • *(QUEUE **) &((*( &loop->wq ))[0])->
  • *(QUEUE **) &(( loop->wq )[0])->
  • *(QUEUE **) &( loop->wq[0] )->
  • *(QUEUE **) &loop->wq[0]

这实际上与(QUEUE *)( loop->wq[0] )相同或只是loop->wq[0]

当然,这只有在wq类型为QUEUE时才有效,它只不过是一个由两个 void 指针组成的数组。作者求助于void*因为 afaik 在 C 中不可能对指向自身的指针数组进行 typedef。

顺便说一句QUEUE_INSERT_TAIL是拼接两个列表的代码。这个界面的有趣之处在于,你如何获得每个元素的内容?看看QUEUE_DATA的定义

#define QUEUE_DATA(ptr, type, field)                                          
((type *) ((char *) (ptr) - ((long) &((type *) 0)->field)))

它的用法

struct user_s {
int age;
char* name;
QUEUE node;
};
user = QUEUE_DATA(q, struct user_s, node);

这解析为

  • QUEUE_DATA(q, struct user_s, node)->
  • (struct user_s*) ((char *) (q) - ((long) &((struct user_s*) 0)->node))

它通过减去其QUEUE成员的偏移量来有效地将地址返回给包含结构,因此q的值将调整为它指向的结构(此处user_s)的地址。

相关内容

最新更新