In C, all function calls are made by value. Which essentially means that the called function always gets its own copy of the arguments you pass to it. Same goes with the value you return from the function. There is always a copy of this value given back to the caller. The moment a function finishes execution, all arguments passed to it and local variables declared within it cease to exist.
For example:
int add(int a, int b)
{
int result = a + b;
return result;
}
int main()
{
int p = 3, q = 5;
int r = add(p,q);
}
In this case, a
and b
are copies of p
and q
respectively, and r
is a copy of result
. p
, q
and result
no longer exist after add()
has finished execution.
Now, this is fine for many common use-cases as in the example above. But what if you want to change the value of one of the variables in the calling function from within the called function? You then need to pass the address of the variable, so that the called function can indirectly access the variable in the calling function and update it.
Example:
void inc(int *p)
{
*p = *p + 1;
}
int main()
{
int a = 5;
inc(&a);
}
In this case, the called function gets a copy of the address of a
, called p
, using which it is able to update the memory location holding a
indirectly. This is called dereferencing a pointer.
Now, to address your question, we need to take this one step further - what if we need to update a pointer in the calling function? We need to pass a pointer to the pointer - also called a double pointer.
In your example, we need to update head
, which is already a pointer to a Node. So we need to pass the address of head, for which we need a double pointer.
Hence your code should be:
void test(node **phead)
{
node* new_node = (node*)malloc(sizeof(node));
new_node->data = 5;
new_node->next = *phead;
/* Note the dereferencing here - we update `head` indirectly through a pointer */
*phead = new_node;
}
test(&head);
Otherwise, we would be passing around a copy of head
, which is a pointer, using which you can access the node that head
points to, but not head
itself. If you increment this pointer within your function, the change is not reflected outside, because this copy ceases to exist the moment the function returns.
PS: C++, unlike C, supports call by reference, which means the language transparently handles the pointer management and lets you directly update variables passed to you 'by reference'.