首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C语言 >

libevent中这么定义链表的好处

2012-08-27 
libevent中这样定义链表的好处.我最近在看libevent其中他是这样定义链表的:见libevent/compat/sys/queue.h

libevent中这样定义链表的好处.
我最近在看libevent
其中他是这样定义链表的:
见libevent/compat/sys/queue.h
这样应该算作是改进的单链表了。如果非要用container_of宏的经过两次调用的话,也可以当作双链表。
140 #define LIST_HEAD(name, type) \
141 struct name { \
142 struct type *lh_first; /* first element */ \
143 }
144 
145 #define LIST_HEAD_INITIALIZER(head) \
146 { NULL }
147 
148 #define LIST_ENTRY(type) \
149 struct { \
150 struct type *le_next; /* next element */ \
151 struct type **le_prev; /* address of previous next element */ \
152 }

这种定义方法和我们常用的定义方法他的好处
为什么不这样定义呢?

140 #define LIST_HEAD(name, type) \
141 struct name { \
142 struct type *lh_first; /* first element */ \
143 }
144 
145 #define LIST_HEAD_INITIALIZER(head) \
146 { NULL }
147 
148 #define LIST_ENTRY(type) \
149 struct { \
150 struct type *le_next; /* next element */ \
151 struct type *le_prev; /* here */ \
152 }


我想了想, 前者定义方法的好处应该是:
插入的时候好使用方便。主要是插入或者删除头部指向的元素时方便,还能保留head的有效性。
比如这个是在元素前面插入时的宏
182 #define LIST_INSERT_BEFORE(listelm, elm, field) do { \
183 (elm)->field.le_prev = (listelm)->field.le_prev; \
184 (elm)->field.le_next = (listelm); \
185 *(listelm)->field.le_prev = (elm); \
186 (listelm)->field.le_prev = &(elm)->field.le_next; \
187 } while (0)

这样,即使链表中的listelm就是head->lh_first指向的,那么在插入后,head也会改变。因为first->lh_first->le_prev == &first->lh_first

但如果使用通常情况的双链表定义的话,head->lh_first是没法改变的! 因为没有无法得到指向head->lh_first的指针。而前者有。

在linux内核中struct hlist也是差不多这样定义的。



[解决办法]
因为编程便利性的需求, 已经习惯让head=NULL代表链表为空了,并且是没有头结点的。
还有就是你贴的代码了,结点里存其他结点的next指针,目的就是免去复杂的判断逻辑,因为链表长度是1,2的时候真的判断的很累。

热点排行