1

我正在查看两个链表实现(queue.h [ source ] 和utlist.h [ source ]),我对它们各自的实现有一些疑问:

  1. _Q_INVALIDATEqueue.h中的全部内容是什么?我想这是一些调试的一部分,但我不太了解宏观define逻辑。
  2. 两种实现都提供FOREACHFOREACH_SAFE. 前者是直截了当的,但第二个背后的逻辑是什么?另外,如果前者无论如何都不安全,那为什么要首先实施呢?
  3. 为什么将queue.h其结构实现为具有不同类型的nextand prev( struct *le_nextand struct **le_prev)?
  4. 在这两种实现中,为什么要在这里和那里插入额外的括号?例如。head在附近#define LIST_FIRST(head) ((head)->lh_first)
4

1 回答 1

4

对于问题 1:

_Q_INVALIDATE是一个宏,它设置一个不应再用于 的值的指针-1。其目的是,如果随后使用它,调试将变得更容易,因为使用指针会导致立即崩溃。在非调试模式下,宏什么都不做,因此指针保留其当前值 - 如果存在导致使用指针的错误,则问题可能是一个更微妙的缺陷。

对于问题 2:

这些宏的“安全”版本采用一个额外的指针参数,宏在内部使用该参数指向列表中的下一项,同时处理当前项。这允许循环内的代码从列表中删除当前项目。由于下一项已经在临时指针中被记住,宏在下一次迭代中拾取它没有问题。宏的非安全版本不使用临时指针,因此您无法在迭代时从列表中删除当前项目。

对于问题 3:

这使得在当前元素之前添加新元素或从列表中删除当前元素更容易,而无需担心当前元素是否位于列表的头部(因此仅由列表指针“指向”)或如果当前元素在列表中的其他位置(因此由另一个元素的le_next指针指向)。如果le_prev是,struct type*那么处理列表中的第一个元素将需要特殊情况代码。由于le_previs astruct type**它可以引用一个简单的struct type*(如列表头指针),就像struct type*嵌入在内部任意偏移量的a type(如le_next每个元素中的链接)一样容易。

问题 4 在上面的评论中得到了回答。

于 2013-05-17T08:17:47.570 回答