2012-12-23 92 views
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); 
} 

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

+1

'bar'正在通过地址(即它的热点)传递。你在遍历期间修改存储在指针数组中的底层指针。用'bar [i]'作为参数输入来调用你的原始行走功能,它应该像你期望的那样工作。 – WhozCraig

回答

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*函数,在性能方面是一个坏主意。