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 **
。
但这有两个原因:
- 您想要更改函数参数
headRef
(struct node *
。 您已将headRef
的地址传递给函数,因为C是按值传递的,因此要更改变量,您需要它的地址。 您想要更改的变量是一个地址,因此您将指针传递给指针,struct node **
:需要额外的间接级别,以便您可以更改函数中的地址,并反映该更改outidefunction。 因此在函数中你需要取消引用变量以获得你想要改变的内容:在你的函数中,你想要改变*headRef
, 而不是headRef
。 - 获取
newNode
的地址会创建一个不必要的间接级别。 如上所述,您要分配的值是newNode
持有的地址, 而不是newNode
的地址。
headRef = &newNode
是一个本地赋值,因此赋值仅在Push
函数范围内有效。 如果在Push
之外可以看到对headRef
更改,则需要执行*headRef = newNode
。 而且,这两者并不相同。 headRef = &newNode
将节点指针的地址分配给指向节点指针的指针,而*headRef = newNode
使用间接将节点的地址分配给指向节点的指针。
你设置headRef
来保存堆栈中变量的地址; 一旦Push()
函数返回,堆栈就不再有效,你可以指望它被覆盖。 这是段错的确定方法。