2012-03-17 23 views
2

本書のほとんどの説明では、* listの代わりに** list passingを使用することを主張していますが、私の理解によれば、* listには何も間違いはないと感じています。私が間違っていると誰かが私に詳しく説明してください。例えば、リンクされたリストの頭を削除するには、下のコードが間違っていると作者は言う。RemoveHead(ノード)関数で** head(および* headではない)を使用する理由は?

void RemoveHead(node *head) 
{ 
    node *temp = head-> next; /* line 1 */ 
    free(head); 
    head = temp; 
} 

代わりに、彼は次のコードは、あなたの最初の例では

void RemoveHead(node **head) 
{ 
    node *temp = (*head)-> next; 
    free(*head); 
    *head = temp; 
} 
+4

これはC++の質問より多くのものです。 C++ではおそらく 'node *&'を渡すべきですが、私は実際のC++コードでこのように何回も見たことがあるので、タスクを削除していません。 –

+0

私の署名は 'node * RemoveHead(node * head)'でしたが... –

答えて

3

関数内の整数変数を変更する場合は、参照渡しします。つまり、そのアドレスを渡します。

int x = 5; 

void modify_value (int* x) 
{ 
    (*x) = 7; // is not 5 anymore 
} 

ポインタは同じです。ポインタを変更したい場合。あなたは参照することによってそれを渡す必要があります。つまり、そのアドレスを渡す必要があります。これはポインタへのポインタです。

int* ptr_x = &x; 

void modify_pointer (int** ptr_x) 
{ 
    *ptr_x = NULL; // is not &x anymore 
} 
8

を使用しなければならないと言う:

head = temp; 

は、関数の外何もしません、それだけでtempにローカル変数headを設定し、関数の中で。呼び出し元が渡した変数は変更されません。作者は正しいですが、ポインタや(より良い)参照を使用する必要があります(C++を使用している場合)。

2

著者は正しいです。あなたの最初の例では、ローカルコピーheadを変更しています - 呼び出し元は何かが変更されたことに気付かないでしょう。 headはまだ解放されているので、かなり短期間でクラッシュする可能性があります。呼び出し側の変数を変更するには、ポインタを渡す必要があります。

+0

答えをどうもありがとうございました。例を挙げて説明してください。申し訳ありません。私は混乱しています – user1276319

+0

C FAQは素晴らしいあなたのQ&A:http://c-faq.com/ptrs/passptrinit.html –

3

引数としてnode*を渡すと、そのポインタが指すメモリアドレスのの内容をの内容に変更することができます。ただし、ポインターが値渡しされるので、ポインター自体に対して実行された変更は関数の外部からは見られません。

2番目の例では、ヘッドポインタにポインタを渡しているので、実際にヘッドポインターを指すメモリだけでなく、実際にヘッドポインタを変更できます。

したがって、2番目の関数では、*head = temp;が実行されたときに、引数が指すポインターが渡されたアドレスを変更しています。

したがって、著者は正しいです。

3

著者は正しいです。 **は実際に参照渡しです(つまり、あなたは「頭」を変えることができます)。

バージョン(値渡し)では、ヘッドは呼び出しコードに変更されません。

関連する問題