-1
#include <stdlib.h>
int malloc2(int **a) {
  *a = malloc(sizeof (int));
return 0;

}
int main() {
  int* b = NULL;
  malloc2(&b);
}

If an argument only accepts double pointers, how can it accept an address value?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Salty
  • 21
  • 5

2 Answers2

0

If not to pass the pointer b by reference through a pointer to it then the function will deal with a copy of the value of the pointer

Changing the copy within the function will not influence on the original pointer.

As a result there the function produce a memory leak.

To change the original pointer b the function needs a direct access to the pointer. It can be achieved by dereferencing the pointer that points to the pointer (object) b.

Compare these two demonstrative programs.

#include <stdio.h>

void f( int *p )
{
    ++p;
    printf( "Within the function f p = %p\n", ( void * )p );
}

int main(void) 
{
    int x = 10;
    int *p = &x;
    
    printf( "Before calling f p = %p\n", ( void * )p );
    
    f( p );
    
    printf( "After  calling f p = %p\n", ( void * )p );

    return 0;
}

The program output is

Before calling f p = 0x7ffc3a940cbc
Within the function f p = 0x7ffc3a940cc0
After  calling f p = 0x7ffc3a940cbc

as you can see the pointer p declared in main was not changed after calling the function f.

And another program

#include <stdio.h>

void f( int **p )
{
    ++*p;
    printf( "Within the function f p = %p\n", ( void * )p );
}

int main(void) 
{
    int x = 10;
    int *p = &x;
    
    printf( "Before calling f p = %p\n", ( void * )p );
    
    f( &p );
    
    printf( "After  calling f p = %p\n", ( void * )p );

    return 0;
}

The program output is

Before calling f p = 0x7ffe011131ec
Within the function f p = 0x7ffe011131f0
After  calling f p = 0x7ffe011131f0

Now you can see that the pointer p declared in main was changed after calling the function f because it was passed to the function by reference through a pointer to it. Dereferencing the pointer to pointer the function gets the direct access to the pointer p declared in main.

If an argument only accepts double pointers, how can it accept an address value

Each value is interpreted according to its type. The value of this expression &b has the type int **. And the function parameter also has the type int **.

You may imagine the function definition and its call the following way

int main() {
  int* b = NULL;
  malloc2(&b);
}
//...
int malloc2( /* int **a */ ) {
  int **a = &b; 
  *a = malloc(sizeof (int));
return 0;
}

That is the function parameter a is initialized by the value of the expression &b.

Or a more simple example

int main( void )
{
    int x = 10;
    int *b = &x;
    int **a = &b;
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • I poorly phrased this post as it was a 2 part question, what I also wanted to understand is why we pass an address (in this case `&p`) , it wasn't quite intuitive to me that doing so acts as a double pointer which the function accepts – Salty Feb 20 '21 at 16:34
  • @FilipTomic Reread my answer one more. There is all written clear with demonstrative programs. The function in your question tries to change the original pointer declared in main. So the pointer shall be passed by reference. Otherwise the function will deal with a copy of the value of the pointer and change the copy instead of the original pointer, – Vlad from Moscow Feb 20 '21 at 16:55
  • I understand that C is a pass by value language and what your post did to overcome that, but I just can't wrap my head around the idea of directly passing an address. How does C treat it as a double pointer? If that address we just passed is a pointer that points to something else other than another pointer to another address, then by definition that can't be a double pointer, right? That's just a single pointer, so what I'm wondering is how C accepts that as a double pointer argument – Salty Feb 20 '21 at 17:07
  • @FilipTomic The expression &b has the type int ** by the definition. And the function parameter has the type int **. So the function parameter is initialized by the value of the expression. – Vlad from Moscow Feb 20 '21 at 17:12
  • @FilipTomic Each value is interpreted by its type. – Vlad from Moscow Feb 20 '21 at 17:13
0

The function accepts a single int ** argument, i.e. a pointer-to-pointer-to-int.

The variable b in main has type int *, i.e. pointer-to-int. If you then take the address of b, you now have a pointer-to-pointer-to-int, i.e. int ** which matches the function's argument.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • I have to ask, is this supposed to be intuitive? Prior to your answer I was trying to imagine sticking an address in the function trying to make sense of it. Now it sort of makes sense but it hasn't quite clicked. How exactly can we just plug in an address of a pointer to an argument? – Salty Feb 20 '21 at 16:46
  • @FilipTomic You can take the address of *any* variable, whether or not it is a pointer type. If a variable has type `int`, its address has type `int *`. If the variable has type `int *`, its address has type `int **`. – dbush Feb 20 '21 at 17:28