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.