Below is my simple linked list in C. My question is in \"headRef = &newNode;\" which causes segmentation fault. Then I tried instead \"*headRef = newNode;\" which resolves the s
You're setting headRef
to hold the address of a variable that lives on the stack; as soon as your Push()
function returns, the stack is no longer valid and you can count on it getting overwritten. This is a sure recipe for a segfault.
You have a fundamental misunderstanding of reference semantics via pointers. Here's the core example:
// 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.
}
So: Caller takes address-of, callee dereferences the pointer and modifies the object.
In your code this means that you need to say *headRef = newNode;
(in our fundamental example, you have T = struct node *
). You have it the wrong way round!
newNode
is already an address, you've declared it as a pointer: struct node *newNode
. With *headRef = newNode
you're assigning that address to a similar pointer, a struct node *
to a struct node *
.
The confusion is that headRef = &newNode
appears to be similarly valid, since the types agree: you're assigning to a struct node **
another struct node **
.
But this is wrong for two reasons:
headRef
, a struct node *
. You've passed the address of headRef
into the function because C is pass-by-value, so to change a variable you'll need it's address. This variable that you want to change is an address, and so you pass a pointer to a pointer, a struct node **
: that additional level of indirection is necessary so that you can change the address within the function, and have that change reflected outide the function. And so within the function you need to dereference the variable to get at what you want to change: in your function, you want to change *headRef
, not headRef
.newNode
is creating an unnecessary level of indirection. The value that you want to assign, as mentioned above, is the address held by newNode
, not the address of newNode
.headRef = &newNode
is a local assignment, so the assignment is only valid within the scope of Push
function. If changes to the headRef
should be visible outside the Push
you need to do *headRef = newNode
. Furthermore, these two are not equivalent. headRef = &newNode
assigns the address of a node pointer to a pointer to node pointer while the *headRef = newNode
assigns the address of a node to a pointer to a node using indirection.