0

I'm trying to understand purpose and how it's works double pointer in this code.

Why we use **p in the declaring function but inside the function we used *p?

void allocate(int** p)
{
  *p = (int*)malloc(sizeof(int));
}

int main()
{
  int *p = NULL;
  allocate(&p);
  *p = 42;
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
obradovic
  • 21
  • 1
  • 6
  • 2
    `**p` is a pointer to a pointer, so `*p` is a pointer to `p` – Ivan Apr 02 '21 at 16:13
  • 1
    https://stackoverflow.com/a/35021864/15160601 – zoldxk Apr 02 '21 at 16:13
  • 1
    `int **` is a "pointer to pointer to int". `double *` is a double pointer. – William Pursell Apr 02 '21 at 16:14
  • 1
    `int**` is conceptually the same as `int*` except that the address it holds is that of an `int*` instead of an `int`. If you understand the example after removing one level of pointer everywhere then understanding this example is the same process. If you don't understand the simpler version, I'd recommend studying that instead. – chris Apr 02 '21 at 16:17

2 Answers2

1

The function's parameter p has type pointer-to-pointer to int, i.e. int **. So referring to p refers to an object of that type.

The expression *p dereferences p giving you an expression (which is also an lvalue) of type int *. This matches the type of p in the main function, and actually refers to that object. This allows us, inside the function allocate, to modify the value of p in main to contain the address of a dynamically allocated block of memory.

dbush
  • 205,898
  • 23
  • 218
  • 273
0

To change the original pointer p declared within the function main in function allocate you need to pass it by reference. Otherwise the function will deal with a copy of the value of the original pointer p and changing the copy will not influence on the value stored in the original pointer.

In C passing by reference means passing an object indirectly through a pointer to it. So dereferencing the pointer you will get an access to the original object.

Consider the following demonstrative program.

#include <stdio.h>

void f( int x )
{
    x = 20;
}

int main(void) 
{
    int x = 10;
    
    printf( "Before calling the function d c = %d\n", x );
    
    f( x );
    
    printf( "After  calling the function d c = %d\n", x );

    return 0;
}

Its output is

Before calling the function d c = 10
After  calling the function d c = 10

As you can see the original variable x was not changed after calling the function f because the variable is passed by value to the function.

Now consider the following program.

#include <stdio.h>

void f( int *px )
{
    *px = 20;
}

int main(void) 
{
    int x = 10;
    
    printf( "Before calling the function d c = %d\n", x );
    
    f( &x );
    
    printf( "After  calling the function d c = %d\n", x );

    return 0;
}

At this time the program output is

Before calling the function d c = 10
After  calling the function d c = 20

As the variable x was passed by reference then dereferencing the pointer px

*px = 20;

you get a direct access to the original variable x through the pointer.

So if you want to change a pointer itself then passing it by reference means passing a pointer to the pointer the same way as it was done in the function above only now the type of the original variable p is int * instead of int.

That is if you have a declaration like this

T x;

where T is some type (as for example int or int *) then to pass the variable by reference you need to use a function argument expression like &x. that will have the type T *. If T is equivalent to the type int * then you need to use an argument expression of the type int **.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335