This function
void test(char *ptr)
{
ptr = malloc(10);
}
that shall be declared before its usage in main deals with a copy of the value of the passed argument in main
char *ptr_main;
test(ptr_main);
You can imagine the function call and the function definition the following way
char *ptr_main;
test(ptr_main);
//...
void test( /* char *ptr */ )
{
char *ptr = ptr_main;
ptr = malloc(10);
}
So as you can see within the function it is the local variable ptr that is changed. The argument ptr_main that was not initialized in main and has indeterminate value stays unchanged.
To change the original pointer ptr_main you have to pass it to the function by reference.
In C the mechanism of passing by reference is implemented by passing an object indirectly through a pointer to it.
From the C Standard (6.2.5 Types)
— A pointer type may be derived from a function type or an object
type, called the referenced type. A pointer type describes an object
whose value provides a reference to an entity of the referenced
type. A pointer type derived from the referenced type T is sometimes
called ‘‘pointer to T’’. The construction of a pointer type from a
referenced type is called ‘‘pointer type derivation’’. A pointer type
is a complete object type.
So the function definition should look like
void test( char **ptr )
{
*ptr = malloc(10);
}
And called like
test( &ptr_main );
Thus dereferencing the pointer ptr in the function we get a direct access to the pointed object (pointer) ptr_main and it is the pointed (referenced) object that is changed now in the function
To make it more clear consider the following demonstrative program.
#include <stdio.h>
#include <stdlib.h>
void f1( int *px )
{
*px = 10;
}
void f2( int **ppx )
{
*ppx = malloc( sizeof( int ) );
**ppx = 20;
}
int main(void)
{
int x = 0;
printf( "Before calling f1 x = %d\n", x );
f1( &x );
printf( "After calling f1 x = %d\n", x );
int *px = &x;
printf( "Before calling f2 px = %p and *px = %d\n", ( void * )px, *px );
f2( &px );
printf( "After calling f2 px = %p and *px = %d\n", ( void * )px, *px );
free( px );
return 0;
}
The program output might look like
Before calling f1 x = 0
After calling f1 x = 10
Before calling f2 px = 0x7ffe79dd572c and *px = 10
After calling f2 px = 0x55db88f5d270 and *px = 20
To change the object x declared in main in the function f1 we need to pass it to the function by reference. Otherwise the function will deal with a copy of the value of the object.
The same situation takes place with the pointer px. Pointers are objects. If we want to change the pointer px declared in main in the function f2 we need to pass it to the function by reference. Otherwise the function will deal with a copy of the value of the object.
And as you can see from the program output the function f2 indeed changed the value of the pointer px declared in main.