1

以下はCでの私の単純なリンクリストです。私の質問は「headRef=&newNode;」にあります。これにより、セグメンテーション違反が発生します。次に、代わりに「* headRef=newNode;」を試しました。これにより、セグメンテーション違反の問題が解決されます。2行のコードは同じように機能しているように見えますが、一方がセグメンテーション違反を引き起こし、もう一方がそうではないのはなぜですか?前もって感謝します。

struct node{
  int data;
  struct node* next;
};

void Push(struct node** headRef, int data){
  struct node* newNode = malloc(sizeof(struct node));
  if(!newNode) return;
  newNode->data = data;
  newNode->next = *headRef;
  headRef = &newNode;
  return;
}
4

4 に答える 4

1

newNodeはすでにアドレスです。ポインタとして宣言しています: struct node *newNode. その*headRef = newNodeアドレスを同様のポインター astruct node *から aに割り当てていますstruct node *

混乱は、タイプが一致するため、同様に有効であるようにheadRef = &newNode 見えることです:あなたはstruct node **別のものに割り当てていますstruct node **

しかし、これは次の 2 つの理由から間違っています。

  1. headRef関数の引数aの値を変更したいとしますstruct node *。Cは値渡しであるため、関数にアドレスを渡しました。変数を変更するには、そのアドレスが必要です。headRef変更するこの変数アドレスであるため、ポインターをポインターに渡します。関数内でアドレスを変更し、その変更を関数のstruct node **に反映させるには、追加レベルの間接参照が必要です。したがって、関数内では、変数を逆参照して、変更したいものを取得する必要があります。関数では、 ではなくを変更します。*headRef headRef
  2. のアドレスを取ることnewNodeは、不必要なレベルの間接性を生み出しています。前述のように、割り当てる値は、 のアドレスではなく、が保持 するアドレスですnewNode newNode
于 2012-08-21T17:03:30.257 に答える
1

ポインターを介した参照セマンティクスについて根本的な誤解があります。コアの例は次のとおりです。

// Call site:
T x;
modify(&x);         // take address-of at the call site...

// Callee:
void modify(T * p)  // ... so the caller takes a pointer...
{
    *p = make_T();  // ... and dereferences it.
}

そのため、呼び出し元はアドレスオブを受け取り、呼び出し先はポインターを逆参照してオブジェクトを変更します。

あなたのコードでは、これはあなたが言う必要があることを意味します*headRef = newNode;(私たちの基本的な例では、あなたは を持っていますT = struct node *)。あなたはそれを間違った方法で持っています!

于 2012-08-21T17:05:08.403 に答える
0

headRef = &newNodePushはローカル割り当てであるため、割り当ては関数の範囲内でのみ有効です。への変更が のheadRef外部に表示される必要があるPush場合は、 を実行する必要があります*headRef = newNode。さらに、これら2つは同等ではありません。headRef = &newNodeはノード ポインタのアドレスをノード ポインタへのポインタに*headRef = newNode割り当て、 はノードへのポインタにノードのアドレスを間接指定を使用して割り当てます。

于 2012-08-21T17:05:23.373 に答える
0

headRefスタック上に存在する変数のアドレスを保持するように設定しています。関数が返されるとすぐPush()に、スタックは無効になり、上書きされることに期待できます。これはセグメンテーション違反の確実なレシピです。

于 2012-08-21T17:05:36.120 に答える