下面是我在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;
}
答案 0 :(得分:1)
newNode
已经是一个地址,您已将其声明为指针:struct node *newNode
。使用*headRef = newNode
,您将该地址分配给类似的指针,struct node *
到struct node *
。
令人困惑的是,headRef = &newNode
似乎同样有效,因为类型同意:您正在分配给struct node **
另一个struct node **
。
但这有两个原因:
headRef
的值,struct node *
。您已将headRef
的地址传递给函数,因为C是按值传递的,因此要更改变量,您需要它的地址。要更改的变量是一个地址,因此您将指针传递给指针struct node **
:需要额外的间接级别,以便您可以更改地址该功能,并将该更改反映为 outide 该功能。因此,在函数中你需要取消引用变量以获得你想要改变的内容:在你的函数中,你想要改变*headRef
,而不是 { {1}}。headRef
的地址正在创建一个不必要的间接层。如上所述,您要分配的值是 newNode
所持有的地址,不 的地址 {{ 1}}。答案 1 :(得分: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 *
)。你有错误的方法!
答案 2 :(得分:0)
headRef = &newNode
是一个本地赋值,因此赋值仅在Push
函数的范围内有效。如果headRef
的更改应在Push
之外显示,则需要*headRef = newNode
。而且,这两者并不相同。 headRef = &newNode
将节点指针的地址分配给指向节点指针的指针,而*headRef = newNode
使用间接将节点的地址分配给指向节点的指针。
答案 3 :(得分:0)
您正在设置headRef
以保存堆栈中存在的变量的地址;只要您的Push()
函数返回,堆栈就不再有效,您可以指望它被覆盖。这是段错误的确定方法。