C指针指针和seg错误



下面是我在C中的简单链表。我的问题是"headRef=&newNode;",这会导致分段错误。然后我尝试了"*headRef=newNode;",它解决了seg故障问题。虽然这两行代码在我看来是以相同的方式工作的,但为什么其中一行代码会导致seg故障,而另一行代码不会?提前谢谢。

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;
}

您对指针引用语义有一个根本性的误解。以下是核心示例:

// 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 *)。你找错地方了!

newNode已经是一个地址,您已经将其声明为指针:struct node *newNode。使用*headRef = newNode,您将该地址分配给类似的指针,struct node *分配给struct node *

令人困惑的是,headRef = &newNode看起来同样有效,因为类型一致:您正在将另一个struct node **分配给struct node **

但这是错误的,有两个原因:

  1. 您想要更改函数参数headRef(一个struct node *)的值。您已经将headRef地址传递到函数中,因为C是按值传递的,所以要更改变量,您需要它的地址。您要更改的变量是地址,因此您将指针传递给指针struct node **:需要额外的间接级别,以便您可以更改函数内的地址,并将该更改反映在函数外。因此,在函数中,您需要取消引用变量以获得您想要更改的内容:在函数中您想要更改*headRef,而不是headRef
  2. newNode的地址会产生不必要的间接级别。如上所述,您要分配的值是newNode持有的地址,而不是newNode的地址

headRef = &newNode是本地赋值,因此该赋值仅在Push函数的范围内有效。如果对headRef的更改应该在Push之外可见,则需要执行*headRef = newNode。此外,这两者并不等同。CCD_ 25将节点指针的地址分配给指向节点的指针,而CCD_。

您将headRef设置为保存堆栈上的变量的地址;一旦Push()函数返回,堆栈就不再有效,您可以指望它会被覆盖。这肯定是一个segfault的配方。

相关内容

  • 没有找到相关文章

最新更新