Reputation: 1144
I have a structure called node:
typedef struct node
{
int x;
struct node *next;
}node;
I have two functions change1() and change2() that allocate memory to the node. change1() takes pointer to the node and change2() takes pointer to pointer as argument.
void change1(node ** n)
{
*n = malloc(sizeof(node));
}
void change2(node * n)
{
n = malloc(sizeof(node));
}
If I call change2(&n) & then try to allocate a value to x (in main after returning from function call to change2) and print it, I get 4 as output but if I call change1(n) & do the same I get a segmentation fault.
void main()
{
node * n1,*n2 ;
change1(&n1); // Pretty much OK
change2(n2); // Leads to segmentation fault on printing
n1->x = 4;
n2->x = 4;
printf("%d ",n1->x);
printf("%d ",n2->x); // gives SEGMENTATION fault
}
Can someone explain what is happening in terms of memory allocation and why the pointer that I'm sending as n2 unable to reflect change after returning to main(). Thanks!
Upvotes: 0
Views: 95
Reputation: 34829
In the second function, n
is a pointer to a node
. Therefore, the second function is only able to modify the members of the node, e.g.
void change2( node *n )
{
n->x = 4;
n->next = NULL;
}
However, this assumes that main
has provided the memory to store the node. So main
would have to do one of the following
int main( void )
{
node n2; // allocate n2 on the stack
change2( &n2 ); // pass the address of the node to the change2 function
printf( "%d\n", n2.x ); // use 'dot' notation to access members of struct
}
--- OR ---
int main( void )
{
node *n2; // n2 is a pointer on the stack
n2 = malloc(sizeof(node)); // allocate memory to store the node data
change2( n2 ); // pass the pointer, i.e. pass the address of the node to the change2 function
printf( "%d\n", n2->x ); // use pointer notation, since n2 was declared as a pointer
}
The third alternative, as mentioned by abligh
is to allocate memory in the function and return the pointer to main.
node *create2( void )
{
node *n2; // declare the pointer
n2 = malloc(sizeof(node)); // allocate memory to store the node data
n2->x = 4; // initialize the members of the node
n2->next = NULL;
return( n2 ); // return a pointer to the node
}
int main( void )
{
node *n2; // n2 is just a pointer
n2 = create2(); // allocate memory for and initialize a node
printf( "%d\n", n2->x ); // use pointer notation, since n2 is as a pointer
}
Upvotes: 0
Reputation: 27632
For a moment, ignore the fact the n1 and n2 are pointers. Just look at them as any other variables.
C only has "call by value", which means that when you call a function, the values of the arguments are copied, and those copies are sent to the function. If you call a function with a variable as argument, its value is copied and sent. This means that the called function can't change the content of the variable.
With n1 you use the "address-of" operator (&) to get, and then send, a pointer to the variable. The function can use that pointer to change n1.
With n2, you just send the value of the variable, so the function can't change the variable. n2 will keep its old value, which is just whatever garbage happened to be in that memory position.
Later in the program you follow the pointers in n1 and n2 to whatever they point to. Since n2 contains garbage, you get what the C standard calls "undefined behavior", and in this case your program crashed.
Upvotes: 2
Reputation: 25129
When you call change2
it overwrites the value of n
passed with the return value of malloc
, then promptly forgets it. This won't work as the value of n2
in the main()
will remain undefined.
If you don't want to use a pointer to a pointer you will have to use some other mechanism to return the value, e.g.
node * change2()
{
return malloc(sizeof(node));
}
...
n2 = change2();
Upvotes: 1