1

我在使用链接列表时遇到了一些麻烦。我不明白为什么这段代码会毫无问题地遍历和打印链表:

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);
}

我只是想明白为什么。为什么指针在第一种情况下没有被重新分配,而在第二种情况下呢?我认为这与传递值与传递引用有关,但这意味着第一个函数也会破坏列表。谁能提供一些见解?

4

1 回答 1

2
void print(struct foo* bar)
{
    while (bar != NULL)
    {
        printf("%d, bar->data);
        bar = bar->next;
    }
}

此函数将 acopy 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;
        }
}

此函数将 acopy of a pointer to pointer to struct foo作为第一个参数。再一次,原来指向指针的指针不能从这里修改,另一方面它指向的值,也就是pointer to foo这里,可以修改。当然,bar指向的指针指向的值,也可以修改。

如果您正确理解了这一点,您应该意识到为什么传递struct something而不是struct something*函数在性能方面是一个坏主意。

于 2012-12-23T03:51:12.833 回答