我对链接列表有点麻烦。我不明白为什么这段代码会遍历并打印链表而没有问题:
struct foo {
int data;
struct foo * next;
};
int main(void) {
struct foo * bar = NULL;
...
print(bar);
}
void print(struct foo * bar) {
while (bar != NULL) {
printf("%d, bar->data);
bar = bar->next;
}
}
然而,当我将列表放在另一个结构(如数组)中时,列表会在遍历期间被销毁,因为指针会在bar[i] = bar[i]->next
处重新分配:
struct foo {
int data;
struct foo * next;
};
int main(void) {
struct foo ** bar = (struct foo**)malloc(SIZE * sizeof(struct foo*));
for (i = 0; i < SIZE; i++)
bar[i] = NULL;
...
print(bar);
}
void print(struct foo ** bar) {
for (i = 0; i < SIZE; i++)
while (bar[i] != NULL) {
printf("%d, bar->data);
bar[i] = bar[i]->next;
}
}
为什么会这样?我知道在这种情况下编写print
函数的正确方法是:
void print(struct foo ** bar) {
struct foo * helper;
for (i = 0; i < SIZE; i++)
for (helper = foo[i]; helper != NULL; helper = helper->next)
printf("%d", helper[i]->data);
}
我只是想了解为什么。为什么指针不能在第一个场景中重新分配,而是在第二个场景中重新分配?我认为它与传递值和传递引用有关,但这意味着第一个函数也会破坏列表。任何人都可以提供一些见解吗?
答案 0 :(得分:2)
void print(struct foo* bar)
{
while (bar != NULL)
{
printf("%d, bar->data);
bar = bar->next;
}
}
此函数将copy of a pointer to struct foo
作为第一个参数。无论函数用它做什么,我都确信原始指针不会被修改,因为我只是在这里处理一个副本。另一方面,指针指向的值可能会被修改。
void print(struct foo** bar)
{
for (i = 0; i < SIZE; i++)
while (bar[i] != NULL)
{
printf("%d, bar->data);
bar[i] = bar[i]->next;
}
}
此函数将copy of a pointer to pointer to struct foo
作为第一个参数。再次,不能从这里修改指向指针的原始指针,另一方面它指向的值(这里是pointer to foo
)可以被修改。当然,bar指向的指针指向的值也可以修改。
如果您已正确理解这一点,您应该意识到为什么将struct something
而不是struct something*
传递给函数,这在性能方面是一个坏主意。