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困惑的是headRef = &newNode 似乎同样有效,因为类型一致:您正在为struct node **分配另一个struct node **

但这有两个原因:

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

headRef = &newNode是一个本地赋值,因此赋值仅在Push函数范围内有效。 如果在Push之外可以看到对headRef更改,则需要执行*headRef = newNode 。 而且,这两者并不相同。 headRef = &newNode将节点指针的地址分配给指向节点指针的指针,而*headRef = newNode使用间接将节点的地址分配给指向节点的指针。

你设置headRef来保存堆栈中变量的地址; 一旦Push()函数返回,堆栈就不再有效,你可以指望它被覆盖。 这是段错的确定方法。