我正在查看两个链接列表实现(queue.h [source]和utlist.h [source]),我对它们各自的实现有几个问题:
_Q_INVALIDATE
是什么?我想这是一些调试的一部分,但我并不真正理解宏define
逻辑。FOREACH
和FOREACH_SAFE
。前者是直截了当的,但第二种背后的逻辑是什么?另外,如果前者无论如何都不安全,为什么它首先被实施?queue.h
将其结构实现为next
和prev
(struct *le_next
和struct **le_prev
)的不同类型?head
#define LIST_FIRST(head) ((head)->lh_first)
左右
醇>
答案 0 :(得分:4)
问题1:
_Q_INVALIDATE
是一个宏,它将不再使用的指针设置为-1
的值。目的是如果随后使用它,调试将变得更容易,因为使用指针将导致立即崩溃。在非调试模式下,宏不执行任何操作,因此指针保留其当前值 - 如果存在导致指针被使用的错误,则问题可能是一个更微妙的缺陷。
问题2:
这些宏的“安全”版本采用了一个额外的指针参数,宏在内部使用该参数指向列表中的下一个项目,同时处理当前的一个。这允许循环内的代码从列表中删除当前项。由于下一个项目已经在temp指针中被记住,因此宏在下一次迭代中拾取它没有问题。宏的非安全版本不使用临时指针,因此在迭代时不能从列表中删除当前项。
问题3:
这样可以更容易地在当前元素之前添加新元素或从列表中删除当前元素,而无需担心当前元素是否位于列表的开头(因此仅列表的'指向'指针)或者当前元素是否在列表中的其他位置(因此由另一个元素的le_next
指针指向)。如果le_prev
是struct type*
,那么处理列表中的第一个元素将需要特殊的案例代码。由于le_prev
是struct type**
,因此它可以引用简单的struct type*
(就像列表头指针一样),就像struct type*
一样容易嵌入{type
内的任意偏移量le_next
1}}(与每个元素中的{{1}}链接一样)。
上述评论回答了问题4。