0

I understand what a pointer is, but I am struggling to understand what they are used for. I could think of situations where you COULD use a pointer, but these situations I can think of, could also be solved in a different way without much more work. Anyway, what I really do not understand, is the use of pointers to pointers. For example I came across this simple C-code:

#include <stdlib.h>

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

From what I understood, this is meant to be a program that can be called by the commandline with infinite parameters and is sort of a convention. What exactly is the purpose of char** argv? Why use a pointer to a pointer to a char here? I'm sorry if this is a trivial question, but I seem to really struggle to get the big picture here.

Thank you in advance, Sparkas

Sparkas
  • 143
  • 1
  • 9
  • 4
    possible duplicate of [How do pointer to pointers work in C?](http://stackoverflow.com/questions/897366/how-do-pointer-to-pointers-work-in-c) – Giorgi Moniava Sep 05 '15 at 17:33
  • 1
    `argv` is (a pointer to the first element of) an array of `char*`. The array's length is `argc`. Normal array-to-pointer decay applies. – molbdnilo Sep 05 '15 at 17:34
  • [Uses of pointers in C](http://stackoverflow.com/questions/5337848/could-you-help-me-understand-pointers-please/5341028#5341028) – John Bode Sep 05 '15 at 18:35

3 Answers3

3

A pointer to a pointer (to a pointer..) is useful in all the situations in which you need more than one level of indirection.

In the specific circumstance of char** args you have an array of strings which are the arguments, each string in C is a char* so basically you have some thing like

char** args
        |
         ->  | char* | char* | char* | char* |
                 |       |
                 v       |
                |f|o|o|  |
                         |
                         v
                        |b|a|r|

What's strange about this? Think about that T* defines a type which is a pointer to a T. Now if T == char* then you have that char** defines a pointer to a char*, which in its turn is a pointer to a char.

Remember that in C and C++ a pointer can represent an array.

ElGavilan
  • 6,610
  • 16
  • 27
  • 36
Jack
  • 131,802
  • 30
  • 241
  • 343
  • I would never have guessed that char **args would point to an array of pointers. I would have just assumed it would point to a single pointer. Although I do not understand how this works, it at least helps me to understand why my given example works the way it does, so thank you for the answer! – Sparkas Sep 07 '15 at 18:59
1

There are examples of C where argv is alternately declared as an array of pointers:

char *argv[]

The pointer to pointer syntax:

char **argv

declares a pointer to what could be the first pointer in an array of pointers. Another common usage is for passing a pointer to a pointer to a linked list:

node *head; /* pointer to linked list */
/* ... */
/* pass a pointer to head */
list_function(&head);
/* ... */
/* use and update head */
list_function(node **head){ ... }
rcgldr
  • 27,407
  • 3
  • 36
  • 61
  • Thanks for the answer! I now know that char **argv points to an array, but I would have intuitively used the char *argv[] way if some had asked me to create an array of pointers. I just don't quite understand how the array is created or declared with **argv. I'd normally assume that it's just a pointer to a single pointer, but maybe that's something I will understand once I learn more about pointers. – Sparkas Sep 07 '15 at 18:56
1

Pointers to pointers show up in a number of situations. Probably the most common is when you need a function to write to a pointer argument.

Consider the following:

void foo( T *p ) // for any type T
{
  *p = new_value(); // write to the thing p points to
}

void bar( void )
{
  T var;
  foo( &var ); // foo updates value of var
  ...
}

Here the function foo is updating the variable var defined in bar through the pointer p.

Now let's replace type T with the pointer type Q *:

void foo( Q **p )
{
  *p = new_pointer_value(); // write to the thing p points to
}

void bar( void )
{
  Q *var;
  foo( &var );  // foo updates the value of var
  ...
}

The semantics are exactly the same; we're writing a new value to var. The only difference is that var has a pointer type, so we need to use multiple levels of indirection in foo.

A second common situation is when you have an array of pointers, and you pass that array to another function. For example:

void foo( char **s )
{
  while ( *s )
    puts( *s++ );
}

void bar( void )
{
  char *strings[] = { "blurga", "bletch", "blah", NULL };
  foo( strings );
}

strings is an array of pointers to char; each element of the array is the address of a string literal (or NULL). In the call to foo the array expression strings is converted ("decays") to an expression of type "pointer to pointer to char", and the value of the expression is the address of the first element of the strings array1. Since the first element of the array is a pointer, then the address of the first element is a pointer to a pointer.

The third case is when you're allocating memory for a 2D array by pieces:

T **arr = malloc( sizeof *arr * rows );
if ( arr )
{
  for( size_t i = 0; i < rows; i++ )
  {
    arr[i] = malloc( sizeof *arr[i] * cols );
  }
}


1. Except when it is the operand of the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array.
John Bode
  • 119,563
  • 19
  • 122
  • 198
  • Thanks for the examples, I wouldn't have thought of that and it helps in understanding the use of pointers – Sparkas Sep 07 '15 at 18:57