Reputation: 324
I was creating a program with linked lists in C. I created a head
variable in main
function. Then I passed it by reference to a function insert_at_head(struct node **head)
.
I have another function for inserting at tail. In a base condition, if my list is empty, I want to call insert_at_head(struct node **head)
again. But I am getting confused in passing the actual parameter. Should it be insert_at_head (&(*head))
or insert_at_head (head)
?
Personally, I think both are same, because both of them are passing a double pointer. Which one should I use?
Upvotes: 1
Views: 596
Reputation: 122
Should it be insert_at_head (&(*head)) or insert_at_head (head)?
None of them. They are both wrong and also the same.
If you did the following in your main:
struct node head;
You will start having problems in your code.
You can make it work but it is the wrong way.
To make it work you must do the following in your main:
struct node head;
struct node *phead=&head;
insert_at_head(&phead).
The right way to go is:
struct node *head=NULL;
insert_at_head(&head).
Upvotes: 1
Reputation: 409176
Regarding the insert_at_head
function, you have to remember that in C all arguments are passed by value. That means the value is copied into the argument variable. Inside the function, if you modify the argument variable (like assigning to it) then you only modify the copy, not the original.
If you want to modify the original value, then you have to emulate pass by reference, which can be done by using the address-of operator &
to pass a pointer to the value. If you want to do this for a variable which is a pointer, then you get a pointer to a pointer.
Here's a simple example:
#include <stdio.h>
// Define two global variables
int a = 10;
int b = 20;
void change1(int *x)
{
x = &b; // Make x point to b
}
void change2(int **x)
{
*x = &b; // Make *x point to b
}
int main(void)
{
// Define a pointer variable, and make it point to the global variable a
int *pointer_to_a = &a;
// Will print the value of a, i.e. 10
printf("*pointer_to_a = %d\n", *pointer_to_a);
// Try to change where pointer_to_a is pointing
change1(pointer_to_a);
// Here pointer_to_a is *still* pointing to a, it wasn't changed, will print the value 10
printf("*pointer_to_a = %d\n", *pointer_to_a);
// Do another attempt to change where pointer_to_a is pointing
change2(&pointer_to_a);
// Now pointer_to_a is no longer pointing to a, it points to b and 20 will be printed
printf("*pointer_to_a = %d\n", *pointer_to_a);
}
Getting back to the insert_at_head
function (whose functionality we can only speculate about) I'm guessing it will add to the head of a linked list. It will do that by modifying where the head of the list is pointing.
As seen by the example above, unless we pass a pointer to the pointer, assignments to the head will be lost once the function ends. And this is solved by using pointer to a pointer, and passing the head pointer using the address-of operator &
when calling the function.
Upvotes: 2
Reputation: 9570
In C language, you can't pass a variable by reference.
You can, however, pass a pointer to your variable. Of course the pointer is passed by value. For example, if you declare a varable head
which is a pointer to a structure node
:
struct node* head;
you can prepare a function to operate on such variable:
void insert_at_head(struct node** ptr);
Then you call it with:
insert_at_head(&head);
where operator &
yield a pointer to your variable, i.e. a value of the struct node **
type. That value is passed to the callee.
Of course, another function, say:
void append_at_end(struct node** ptr);
can call the former function when necessary, passing it the same pointer it got as a parameter:
void append_at_end(struct node** ptr)
{
if(*ptr == NULL) /* list is empty */
insert_at_head(ptr); /* the same pointer to a head pointer */
else {
/* other stuff */
}
}
Upvotes: 1
Reputation: 223917
Assuming the type of head
is struct node **
, then you can pass it directly to a function expecting a parameter of that type.
&(*head)
is exactly the same as head
. When the operand of the &
operator is the result of the unary *
operator, they cancel each other out and neither is actually evaluated.
This is spelled out in section 6.5.3.2p3 of the C standard regarding the address-of and indirection operators:
The unary
&
operator yields the address of its operand. If the operand has type ‘‘type’’, the result has type ‘‘pointer to type’’. If the operand is the result of a unary*
operator, neither that operator nor the&
operator is evaluated and the result is as if both were omitted, except that the constraints on the operators still apply and the result is not an lvalue.
So if head
is a pointer, the expressions head
and &(*head)
are equivalent.
Upvotes: 1