Home > Mobile >  Double pointer C/C
Double pointer C/C

Time:07-19

can someone explain to me how double pointers work? On this code for example, why it prints the values that it prints in the end?

int main(void) {
    int anArray[] = {5,16,33,99};
    int * p = anArray;

    printf("*p = %d\n", *p);
    p  ;
    printf("Now *p = %d\n", *p);

    int * q = &anArray[3];
    int ** x = &q;
    **x = 12;
    *x = p;
    **x = 42;
    q[1] = 9;

    for (int i =0; i < 4; i  ){
        printf("anArray[%d] = %d\n",i, anArray[i]);
    }

    return EXIT_SUCCESS;
}

CodePudding user response:

Let's draw out:

int q = 15;
int * p = &q;
int * * z = &p;

            q   
           ----   
    p --> | 15 |  
    ^      ----   
    |  
    z  

In the above drawing, q is an integer variable with the value 15.
The pointer p points to the variable q.
The pointer z points to the pointer p.

The expression *z refers to the value in the pointer p.
The expression **z or rewritten as *(*z) refers to the variable q (following the links).

We know that (*z) is the pointer p, so let's replace:
*(*z) == *(p);

We can replace *(p) with q, from the above definitions: *(*z) == *(p) == q;.

CodePudding user response:

Let's fully draw it out:

int anArray[] = {5,16,33,99};  // 4 values in consecutive addresses

//            ----
// anArray ->   5
//            ----
//             16
//            ----
//             33
//            ----
//             99
//            ----

int * p = anArray; // A new variable, whose contents points to the address of anArray

//            ---------
// anArray ->   5       <- 
//            ---------   |
//             16         |
//            ---------   |
//             33         |
//            ---------   |
//             99         |
//            ---------   |
//       p ->  anArray   - 
//            ---------

printf("*p = %d\n", *p);  // prints 5
p  ;                      // increment pointer p to the next element.

//            -----------
// anArray ->   5      
//            -----------
//             16         <- 
//            -----------   |
//             33           |
//            -----------   |
//             99           |
//            -----------   |
//       p ->  anArray 1   - 
//            ---------

printf("Now *p = %d\n", *p); // prints 16
int * q = &anArray[3];       // new pointer variable, points to 4th element of anArray (0-based)

//            -----------
// anArray ->   5      
//            -----------
//             16         <- 
//            -----------   |
//             33           |
//            -----------   |
//             99           | <- 
//            -----------   |   |
//       p ->  anArray 1   -    |
//            -----------       |
//       q ->  anArray 3   ----- 
//            -----------

int ** x = &q;  // new pointer variable, points to address of q pointer variable

//            -----------
// anArray ->   5      
//            -----------
//             16         <- 
//            -----------   |
//             33           |
//            -----------   |
//             99           | <- 
//            -----------   |   |
//       p ->  anArray 1   -    |
//            -----------       |
//       q ->  anArray 3   -----  <- 
//            -----------           |
//       x ->  q           --------- 
//            -----------

**x = 12;  // get address in x (q), then address in q (anArray 3) and write 12 to it

//            -----------
// anArray ->   5      
//            -----------
//             16         <- 
//            -----------   |
//             33           |
//            -----------   |
//             12           | <- 
//            -----------   |   |
//       p ->  anArray 1   -    |
//            -----------       |
//       q ->  anArray 3   -----  <- 
//            -----------           |
//       x ->  q           --------- 
//            -----------

*x = p;  // get address in x (q) and write p value to it (anArray 1)

//            -----------
// anArray ->   5      
//            -----------
//             16         <-  <- 
//            -----------   |   |
//             33           |   |
//            -----------   |   |
//             12           |   |
//            -----------   |   |
//       p ->  anArray 1   -    |
//            -----------       |
//       q ->  anArray 1   -----  <- 
//            -----------           |
//       x ->  q           --------- 
//            -----------

**x = 42;  // get address in x (q), then address in q (anArray 1) and write a 42 to it

//            -----------
// anArray ->   5
//            -----------
//             42         <-  <- 
//            -----------   |   |
//             33           |   |
//            -----------   |   |
//             12           |   |
//            -----------   |   |
//       p ->  anArray 1   -    |
//            -----------       |
//       q ->  anArray 1   -----  <- 
//            -----------           |
//       x ->  q           --------- 
//            -----------

q[1] = 9;  // get address in q (anArray 1) add one element (anArray 2), and assign 9

//            -----------
// anArray ->   5      
//            -----------
//             42         <-  <-    (q[0])
//            -----------   |   |
//              9           |   |   (q[1])
//            -----------   |   |
//             12           |   |
//            -----------   |   |
//       p ->  anArray 1   -    |
//            -----------       |
//       q ->  anArray 1   -----  <- 
//            -----------           |
//       x ->  q           --------- 
//            -----------

CodePudding user response:

First of all, I will use a simple example to demonstrate double pointers:

int x = 5; // Simply 5
int* y = &x; // y holds the address of x
int** z = &y; // z holds the address of y

When y holds the address of x it means that no matter what is the value of x, y still points to it (points means 'holding the address of'). So, changing x also changes *y which is the syntax for accessing the value that y points to. The same is applied to z, but here we need to use * operator twice in order to access x value, because z points to y which points to x (meaning **z == *y == x).

To understand your question we also need to understand what arrays are in C. Array is a sequence of elements (e.g. integers, chars and etc...) in a contiguous memory location. An array is actually a pointer meaning if we have int anArray[] = {5,16,33,99}; accessing anArray using anArray[0] is the same as *anArray, or anArray[1] is the same as *(anArray sizeof(int)) and etc...

CodePudding user response:

A pointer is a variable holding a memory address which contains the value you want. For example:

int value = 42;
int* value_ptr = &value;
int access_via_ptr = *value_ptr;

A double pointer, or a pointer to pointer, is a variable holding an address of another pointer, which holds an address to the value you want. For example:

int value = 42;
int* value_ptr = &value;
int** value_ptr = &value_ptr;
int access_via_ptr_ptr = **value_ptr;

Why would you want to use **? One really useful way is in functions. You want to pass a pointer to a pointer, so that the function can setup the pointer address for you. For example:

#include <iostream>

void GetPtr(int** val_ptr_ptr, int init_contents)
{
    // val_ptr_ptr should point to a pointer
    // lets allocate it
    *val_ptr_ptr = new int;

    // de-reference ptr->ptr->val to initialize
    // the contents
    **val_ptr_ptr = init_contents;
}

int main(void)
{
    int* val_ptr = NULL;
    GetPtr(&val_ptr, 42);
    std::cout << *val_ptr;
    delete val_ptr;
    return 0;
}

In this example we want a function to allocate memory. We want that memory to be stored in a pointer outside the function, so we can access it. We pass in an address of outside pointer, or a pointer to a pointer. We then assign the address inside the function.

  • Related