2017-08-31 159 views
0

我在網站上找到了這個代碼,用於在列表的開頭插入一個節點到鏈表中。使用指針指向什麼點?

void push(struct Node** head_ref, int new_data) 
{ 
/* 1. allocate node */ 
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node)); 

/* 2. put in the data */ 
new_node->data = new_data; 

/* 3. Make next of new node as head */ 
new_node->next = (*head_ref); 

/* 4. move the head to point to the new node */ 
(*head_ref) = new_node; 
} 

這是呼叫 -

push(&head, 7); 

功能我的問題是,爲什麼通過傳遞地址的指針,然後隨後在函數內部的地址提取的值走很長的路要走。 爲什麼我們不能簡單地傳遞在函數指針head後來作出這樣的分配 -

new_node->next=head_ref; 

+0

[Jagged array](https://en.wikipedia.org/wiki/Jagged_array) –

+2

因爲該函數也改變了'head_ref'的值。由於'head'有指針類型,所以你需要傳遞'push'的指針指針來更新'head'的值。 –

+0

閱讀[this](https://stackoverflow.com/a/897400/971127) – BLUEPIXY

回答

3

如果通過head而不是&head,行

(*head_ref) = new_node; 

將不得不改爲

head_ref = new_node; 

然而,這將是該函數的局部變化。它不會改變調用函數中的head的值。有兩個問題:

  1. 調用函數將永遠不會得到一個工作列表。
  2. 函數中分配的內存將是內存泄漏。
+0

這解釋了它!謝謝! – Vaibhav

+0

@Vaibhav,很高興我能夠幫助。 –

0

調用程序中的變量頭是一個指向列表頭部的指針。你需要一個指向這個變量的指針,以便在push()中更新它。所以你將一個指針傳遞給一個包含指針的變量,以便你可以更新該變量。

2

你也可以寫代碼如下:

struct Node* push(struct Node* head_ref, int new_data) 
{ 
    struct Node* new_node = (struct Node*) malloc(sizeof(struct Node)); 
    new_node->data = new_data; 
    new_node->next = head_ref; 
    return new_node; 
} 

,並調用它,如下所示:

head = push(head, 7); 

它實現了完全一樣的東西,即在頭插入一個新節點然後將head更新爲指向該新節點。但在我看來,這不會是一個好的解決方案,因爲它允許push()函數的調用者忘記將返回的值分配給head,此時您將擁有孤立節點並最終導致內存泄漏。

+0

這不一定是更糟糕的解決方案,它只是增加了要求分配回報。通過將指針傳遞給指向類型...的指針,您可以擁有兩全其美的優點(例如,可以靈活地執行)...返回指向添加的當前節點的指針(用於分配或立即使用)。只要你正確地更新列表引用':'',那麼'技術上'不會比另一個'更正確' –

0

這一切都與您選擇的編程風格有關。使用一組函數來操作列表會使程序在結構上合理。這樣你可以使它更具可讀性。如果您需要從多個位置操作相同的列表或操作多個列表,它也將避免剪切-n粘貼。

你組織你的功能的方式取決於你。我個人喜歡你的例子。在這種情況下,你只需要在參數中指定一個指向頭部的指針。如果從函數返回它,則在程序中使用錯誤指針的風險更高。

'C'有足夠的工具來編寫任何類型的程序。但是有時你需要遵循特定的規則來應用它們,比如你的案例中的指針地址。不是很方便,但可靠,並證明可行。作爲'C'程序員,你會很快習慣它。

你也可以看看有更好的工具,使這更方便的c + +。

相關問題