Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I am familiar with basic C pointers. Just wanted to ask what is the actual use of double pointers or for that matter n pointer?

#include<stdio.h>
int main()
{
int n = 10 , *ptr , **ptr_ptr ;
ptr     = &n;
ptr_ptr = &ptr;
printf("%d",**ptr_ptr);
return(0);
}

**ptr_ptr is printing 10 but how?

share|improve this question
1  
Its a pointer to a pointer. –  MichaelT Jun 26 at 14:56
    
need more elaboration. –  Sandeep Pareek Jun 26 at 15:04
    
Its a pointer that points to a pointer, that points to the address of the integer n. You dereference it once you get the pointer it was pointing to, dereference it twice you get the object pointed to by the pointer ptr_ptr is pointing to. –  noobProgrammer Jun 26 at 15:22
    
I really expected this to be a duplicate, but surprisingly it's not. Definitely worth an answer. –  david.pfx Jun 28 at 7:01

3 Answers 3

ptr_ptr is a pointer to a pointer to an int, and it points at ptr. ptr is a pointer to an int, and it points at n. n is an int, which has been set to 10.

A prefix '*' is the de-reference operator, meaning "the thing pointed to by". So **ptr_ptr evaluates to *ptr which evaluates to n, which is 10. If it helps, consider **ptr_ptr as equivalent to *(*ptr_ptr).

What's it for? Two possible uses are

  1. Passing a pointer as a parameter to a function, where you want the function to be able to change the pointer to a different one.
  2. Passing an array of pointers to a function, as in the classic int main(int argc, char **argv).

I have never encountered any need for an int ***ptr_ptr_ptr, but it's valid C.

share|improve this answer
1  
Only Three Star Programmers use ***foo. –  MichaelT Jun 26 at 15:36
    
Confession time: within the past decade I have worked on C++ classes that used types like double*** -- but I swear they were already that way when I found them. Someone then extended one of those classes to one that uses types like double****. The idea of these types had to do with multidimensional arrays; I'm not saying it was a good idea. –  David K Jun 26 at 20:14

Multiple indirection generally occurs in the following scenarios: writing to a parameter of pointer type, and building an N-dimensional array by pieces.

Writing to a parameter of pointer type

For any function parameter of type T, if you want the function to modify the value of the parameter and have that new value reflected in the caller, you must pass a pointer:

void foo( T *ptr )
{
  *ptr = new_value(); // writes new value to thing pointed to by ptr
}

void bar( void )
{
  T var;
  foo( &var ); // writes new value to var
}

The expression *ptr in foo refers to the same object in memory as var in bar, so writing to *ptr is equivalent to writing to var.

If T is a pointer type Q *, then you wind up with a pointer to a pointer:

void foo( Q **ptr )
{
  *ptr = new_value(); // writes new value to thing pointed to by ptr
}

void bar( void )
{
  Q *var;
  foo( &var ); // writes new value to var
}

In this second case, you want to modify the pointer value stored in var. Again, both *ptr and var refer to the same memory location, but this time, var contains a pointer value. You could replace Q with R *, giving

void foo( R ***ptr )
{
  *ptr = new_value(); // writes new value to thing pointed to by ptr
}

void bar( void )
{
  R **var;
  foo( &var ); // writes new value to var
}

The semantics are the same in all three cases; we write a new value to var through the expression *ptr; it's just the type of var is a pointer type, meaning the type of ptr must be a pointer type with one more level of indirection.

Building an N-dimensional array by pieces

Suppose you want to allocate an NxM array of T, but you don't know the values of N or M at compile time. One approach is to declare a pointer to a pointer, then allocate an array of pointers to it:

T **arr; // arr will point to an NxM array of T
size_t n, m;
/**
 * get values for n and m
 */
arr = malloc( sizeof *arr * n ); // allocate N objects of type T *
if ( arr )
{
  for ( size_t i = 0; i < n; i++ )
  {
    arr[i] = malloc( sizeof *arr[i] * m ); // allocate M objects of type T
    if ( arr[i] )
    {
      for ( size_t j = 0; i < m; i++ )
      {
        arr[i][j] = some_value();
      }
    }
  }
}

The same general mechanism can be applied for higher-dimensioned arrays:

T ***arr3;
...
arr3 = malloc( sizeof *arr3 * n );
...
  arr3[i] = malloc( sizeof *arr3[i] * m );
  ...
    arr3[i][j] = malloc( sizeof *arr3[i][j] * k );

There are a few other scenarios where you see multiple indirection, but those are the two main ones.

It's rare in practice to see more than three levels of indirection, though.

share|improve this answer

A pointer-to-pointer simply means that you have an address of a memory location where some other pointer is stored. You dereference it twice to get to the final typed value.

int i = 123;
int* pi = &i;
int ** ppi = &pi;
int j = **ppi;

There are a surprising number of situations in which you need to use one of these beasties.

  1. As an output argument of a function call, pass a pointer to the pointer you want output or modified.
  2. Accessing an array of C null-terminated strings; each string is itself a pointer. The argc argument to main looks like that.
  3. 'Jagged' or N-dimensional arrays, stored as array of pointer to data. The data will usually be allocated with malloc().
  4. A 'handle' for a memory block, so the owner of the block can move it without the user of the block needing to know.
  5. Manipulating a structure that itself contains pointers, such as linked lists, trees and so on. It's basically impossible to insert an item into a linked list without them.

It's important to keep these conceptually separate. Although they all seem to use the same construct, in reality the underlying purpose is quite different. And I'm sure there are others I've missed.

I won't provide more code. There is an excellent example with diagrams and code here: http://www.eskimo.com/~scs/cclass/int/sx8.html.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.