【发布时间】:2016-01-17 22:25:15
【问题描述】:
我正在查看这段代码,实现了在双向链表中插入元素的操作。我试图理解为什么LIST_APPEND 宏将它附加到列表的末尾,但是,我总是向自己解释它是领先的。代码:
struct link {
struct link *prev;
struct link *next;
};
void insert(struct link *prev, struct link *new, struct link *next)
{
prev->next = new;
new->prev = prev;
next->prev = new;
new->next = next;
}
#define LIST_APPEND(member, list, new) \
insert(list.prev, &(new->member), &list)
我的考虑:
首先,C-Preprocessor 在实际代码中替换宏的内容后,我们得到
void insert(list.prev, &(new->member), &list)
{
(list.prev)->next = (new->member); //1.
(new->member)->prev = list.prev; //2.
list->prev = (new->member); //3.
(new->member)->next = list; //4.
}
对应于:
1.list.prev的next指向(new->member)
2. (new->member)的prev现在是list.prev
3. list的prev现在是(new->member)
4.(new->member)的下一个是list
如果我的逻辑中有流动,它们可能就在这里。
现在为了说明这一点,这里是一个可能的(据我理解)插入的描述。
问题:到底追加是在头部还是尾部?如果是后者,我哪里错了?
【问题讨论】:
-
您能否提供一个如何调用宏的示例?你作为“成员”传递了什么?
-
你应该保护扩展中的宏参数:`#define LIST_APPEND(member, list, new) insert((list).prev, &((new)->member), &(list) )
-
"首先,在 C 预处理器在实际代码中替换宏的内容后,我们得到......" - 不是??预处理器不会改变
insert。它将LIST_APPEND(a, b, c)更改为insert(b.prev, &(c->a), &b)。 -
@immibis 是的,当然。这就是我所说的(意思)。
insert已定义。它只是用宏参数调用它 -
完全偏离主题,但建议您不要调用变量
new,因为这是一个 C++ 关键字。如果你想在未来转向 C++,你只会造成混乱和挖洞。
标签: c insert linked-list macros