2012-12-23 120 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*函數,在性能方面是一個壞主意。