1

I'm new to C, sorry if my question sound dumb. I see some function takes a "double" pointer as parameter, for example:

int main(int argc, char **argv)
{
   ...
}

I can understand the need for a double pointer such as argv, since argv is the pointer to the first element of argument array whose element is also a pointer to a char type. double pointer is needed in this case. But for some functions like:

int getaddrinfo(const char *host, const char *service, const struct addrinfo *hints, struct addrinfo **result);

I don't understand why a double point is needed, since there is no array element involved, and I think getaddrinfo calls malloc internally, so it might be a reason to use double pointer, but we can have sth like this:

int main() 
{
   char *ptr_main;
   test(ptr_main);
   free(ptr_main);
}

void test(char *ptr)
{ 
    ptr = malloc(10); 
}

so the parameter is a single pointer char * ptr, no char **ptr is needed?

Vlad from Moscow
  • 265,791
  • 20
  • 170
  • 303
amjad
  • 3,048
  • 1
  • 11
  • 42
  • "calls malloc internally" is the correct mental model. At which point you should wonder, "wait, shouldn't I release that again?" Yes, call freeaddrinfo(). – Hans Passant Oct 07 '20 at 12:36
  • so did you try your "something like this" yet? – Antti Haapala -- Слава Україні Oct 07 '20 at 12:38
  • If you want to change a variable you pass to a function, you need to pass a pointer to that variable. If that variable is a pointer, then you need a pointer to pointer. If you want to change a pointer to pointer you need a pointer to pointer to pointer, etc. – klutt Oct 07 '20 at 12:42

3 Answers3

0

Passing a pointer, or address of an object allows the value stored at that location in memory to be changed by the function, so when the function returns, the address now contains the updated value. If a function argument needs to accept a pointer variable, and the pointer variable is to be changed, the address to that pointer must be passed, thus requiring the function prototype to be a pointer-to-pointer.

Addressing your question may illustrate: getaddrinfo question: I don't understand why a double point is needed, since there is no array element involved

Usage for this struct is typically:

struct addrinfo *result;//pointer variable
getaddrinfo("hostname", "servicename", NULL, &result);
//                                           |_Passing address of a pointer variable.
//                                             thus requiring prototype to accommodate

So as explained, for the function to receive updated struct information, it needs to send the address of the pointer variable, requiring it to be a double pointer:

int getaddrinfo(const char *host, ..., struct addrinfo **result);
ryyker
  • 21,724
  • 3
  • 41
  • 81
0

Your code is incorrect. ptr is local to the scope of test. A pointer is just a number representing a memory address. You probably wouldn't expect test in the following code to affect the value of number_main, right?

int main() 
{
   int number_main;
   test(number_main);
   printf("%d\n", number_main);
}

void test(int number_main)
{ 
    number_main = 10;
}

Maybe it helps if you internalize char * as some fictional type you'll call number_that_represents_memory_address, which you then think about as no different than int in this case?

gspr
  • 10,861
  • 3
  • 41
  • 72
0

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.

Vlad from Moscow
  • 265,791
  • 20
  • 170
  • 303