What does ** do in C language?

James picture James · Jan 26, 2016 · Viewed 63.9k times · Source

I'm new to C with a good background in java and I'm trying to understand pointers and arrays.

I know that subscript operator[] is part of an array definition, so:

int numbers[] = {1,3,4,5};

would create a integer array, which would be represented in memory as 16 bytes, 4 lots of 4 bytes:

numbers[0] = 1, address 0061FF1C
numbers[1] = 3, address 0061FF20
numbers[2] = 4, address 0061FF24
numbers[3] = 5, address 0061FF28

However, when it comes to pointers my knowledge starts to break down, so if I was to create a pointer to the array numbers I would do the following:

int *pNumbers = &numbers[0];

which would look something like this:

pointer to numbers

And I'm guessing it would be of size 4 bytes?

However the ** I read as "pointer to a pointer" which makes no sense to me, why would anyone want a pointer to a pointer, surely if a->b->c then a->c would suffice? I know I'm missing something, and it must have something to do with arrays as argv can be of type char[ ] or char ** as seen bellow:

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

So:

  • what is this (**)?
  • what use does it have?
  • how is it represented in memory?

Answer

Vlad from Moscow picture Vlad from Moscow · Jan 26, 2016

In C arguments are passed by values. For example if you have an integer varaible in main

int main( void )
{
    int x = 10;
    //...

and the following function

void f( int x )
{
    x = 20;
    printf( "x = %d\n", x );
} 

then if you call the function in main like this

f( x );

then the parameter gets the value of variable x in main. However the parameter itself occupies a different extent in memory than the argument. So any changes of the parameter in the function do not influence to the original variable in main because these changes occur in different memory extent.

So how to change the varible in main in the function?

You need to pass a reference to the variable using pointers.

In this case the function declaration will look like

void f( int *px );

and the function definition will be

void f( int *px )
{
    *px = 20;
    printf( "*px = %d\n", *px );
} 

In this case it is the memory extent occupied by the original variable x is changed because within the function we get access to this extent using the pointer

    *px = 20;

Naturally the function must be called in main like

f( &x );

Take into account that the parameter itself that is the pointer px is as usual a local variable of the function. That is the function creates this variable and initializes it with the address of variable x.

Now let's assume that in main you declared a pointer for example the following way

int main( void )
{
   int *px = malloc( sizeof( int ) );
   //..

And the function defined like

void f( int *px )
{
    px = malloc( sizeof( int ) );

    printf( "px = %p\n", px );
}

As parameter px is a local variable assigning to it any value does not influence to the original pointer. The function changes a different extent of memory than the extent occupied by the original pointer px in main.

How to change the original pointer in the function? Just pass it by reference!

For example

f( &px );
//...

void f( int **px )
{
    *px = malloc( sizeof( int ) );

    printf( "*px = %p\n", *px );
}

In this case the value stored in the original pointer will be changed within the function because the function using dereferencing access the same memory extent where the original pointer was defined.