2017-08-31 3 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); 

call-機能である私の質問は、なぜポインタのアドレスを渡すことで長い道を行く、その後関数内のアドレスに値を抽出することです。 は、なぜ我々は単に機能にポインタheadを渡し、後のような割り当てを行うことはできません -

new_node->next=head_ref; 

+0

[ジャグ付き配列](https://en.wikipedia.org/wiki/Jagged_array) –

+2

この関数は 'head_ref'の値も変更しているためです。 'head'はポインタ型を持っているので、' head'の値を更新するために 'push'のポインタを渡す必要があります。 –

+0

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

答えて

3

(*head_ref) = new_node; 

それは機能の局所的な変化になります、しかし

head_ref = new_node; 

に変更する必要があります。呼び出し元関数のheadの値は変更されません。それには2つの問題があります:

  1. 呼び出し元の関数は決してワーキングリストを取得しません。
  2. 関数に割り当てられたメモリはメモリリークになります。
+0

それはそれを説明します!ありがとう! – Vaibhav

+0

@Vaibhav、私は助けてくれてうれしいです。 –

0

呼び出し元プログラムの変数頭部は、リストの先頭へのポインタです。 push()内で変数を更新するには、この変数へのポインタが必要です。したがって、ポインタを保持する変数へのポインタを渡すので、その変数を更新することができます。あなたがheadなく&head、ラインを通過した場合

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

これは、すべてあなたが選んだプログラミングスタイルに関連しています。一連の関数を使用してリストを操作すると、プログラムは構造的に健全になります。このようにして、読みやすくします。複数の場所から同じリストを操作したり、複数のリストを操作する必要がある場合は、カットアンドペーストも避けます。

あなたの機能を整理する方法はあなた次第です。私は個人的にあなたの例の方法が好きです。この場合、引数の頭にポインタを1回だけ指定する必要があります。代わりに関数から関数を返すと、プログラムで間違ったポインタを使用するリスクが高くなります。

'C'には、あらゆる種類のプログラムを書き込むのに十分なツールセットがあります。しかし、あなたのケースのポインタのアドレスのように、それらを適用するための特定のルールに従う必要があることがあります。それほど便利ではありませんが、信頼性が高く、実績があります。 'C'プログラマーとして、すぐにそれに慣れるでしょう。

これをより便利にするための優れた手段を備えたC++を見ることもできます。

関連する問題