# Thread: Double pointers - C

1. ## Double pointers - C

Hi everybody,

I'm learning C language (actually it's better to say that I'm trying to learn it), and I have some difficulties with the use of double pointers.

I give you an example here:

//BEGINNING OF THE CODE

int a=5;
int b=2;

int *point;
int **doublepointer;

pointer=&a;
/*FIRST QUESTION: now 'pointer' is equal to the adress of 'a', and '*pointer' is equal to the value of 'a' . Is that correct?*/

doublepointer=*pointer;
/*SECOND QUESTION, I'M NOT SURE ABOUT THIS: now 'doublepointer' is equal to the adress of 'pointer', and '*doublepointer' is equal to the value pointed by 'pointer'.
Is that correct? I don't think so. Can anyone correct these sentences?*/

b=*doublepointer;
/*THIRD QUESTION, what happen if I do this?*/

b=**doublepointer;
/*FOURTH QUESTION, what happen if I do this?*/

//TERMINATION OF THE CODE

Sorry if some of these questions were pretty silly, but the use of double pointers is confusing me.
I can't see the whole picture, how can I manage double pointers using one * or two **.

Thanks everybody! 2. Going backwards, assuming:

Code:
```int a = 5;
int b = 2;
int *pointer;
int **dpointer;
```
There's nothing all that mysterious about dpointer. The only real difference in the concept between dpointer and pointer is that where pointer may point to the address of a variable, dpointer points to the address of a pointer. One could argue that dpointer is that singularly special case where the type it points to happens to be a pointer, whereas pointer does not.

That is, where

Code:
```pointer = &a
or
pointer = &b```
This does the same kind of thing

Code:
`dpointer = &pointer`
with the only real exception being that pointer is a pointer, not an integer (or whatever type the pointer is declared to point to).

This means that whatever can be done with a or b can be done with *pointer:

Code:
```//where
pointer = &a;

a = 6;
*pointer = 6;```
Likewise, whatever can be done with pointer can be done with *dpointer

Code:
``` //where
pointer = &a;
dpointer = &pointer;

*pointer = 8;   // which is the same as a = 8;
**dpointer = 8; // same as *pointer = 8

*(*dpointer) = 8; // think of it this way, where *dpointer is the same as pointer```
When used in assignments (not declarations), you can read "*pointer" as: what's stored at pointer.

#1: Yes, a pointer stores the address of something, in this case an integer, such that the "&a" gives the pointer to where a is stored, and pointer = &a copies the address of a to the pointer.

#2: You've written the statement incorrectly. dpointer can't accept *pointer, *pointer is read in this context as "what's stored at" pointer. dpointer is not declared to take that type (it is an integer), dpointer is declared to take the address of a pointer (a double pointer does that). The correct fashion for this example question should be dpointer = &pointer; meaning that dpointer, which is declared to accept the address of a pointer, is assigned to the address of pointer.

#3 If we assume dpointer is correctly assigned to the address of a pointer, as in dpointer = &pointer, we have to qualify this with one important point: we must know that pointer is also valid to use this, so let's assume, for simplicity, that:

Code:
```int a = 5;
int b = 2;
int *pointer;
int **dpointer;

pointer = &a; // pointer is now valid to use
dpointer = &pointer; // dpointer is valid to use

//b = *dpointer; // this is an error and won't compile (usually)
b = **dpointer;
b = *pointer;  // this is the same as **dpointer
```
b is an integer. It can be assigned to another integer, copying the value, as in b = a;

pointer points to an integer, and if assigned as above, what's stored at that pointer is an integer, so b = *pointer;

dpointer points to the address of a pointer to an integer, so what's stored at dpointer is a pointer to an integer. Think of that this way:

Code:
`b = * (*dpointer);`
Here, dpointer is 'dereferenced' inside the parenthesis. Since dpointer is a pointer to a pointer, what is stored at dpointer is a pointer.

That isn't an integer, is a pointer to an integer. To get the integer, it must be dereferenced again, because what "comes out of" of the parenthesis is a pointer, it's just like "pointer", so

Code:
```* (*dpointer);

//is the same as

*pointer;```
So,

Code:
```int a = 5;
int b = 4;

int *pointer = &a;
int **dpointer = &pointer;

**dpointer = 4; // a is now 4

if ( *pointer == b ) // is true```
Now, in closing, this is a crash:

Code:
```int a = 5;
int b = 4;

int *pointer = NULL;
int **dpointer = &pointer; // this is ok but be warned what's next

**dpointer = 3; // this crashes because pointer itself is NULL.

*dpointer = &a; // this does the same as pointer = &a

**dpointer = 2; // this would work if it hadn't crashed above``` 3. Pointer is a variable as any other. I like to explain this way:

This is a DECLARATION of a variable p:
Code:
`int *p;`
Here p will be used to hold the address where an int is, in memory, but it is uninitialized.

When you do:
Code:
```int x;;
int *p;
x = 5;
p = &x;```
The variable p will hold the address-of where variable x is, in memory. And here is another concept: The USE of variables. The int *p, above, is the DECLARATION of a variable, where p = &x; is its USAGE. And you use variables through expressions... p = &x; is the expression "assign to p the address-of x".

Of course, C compilers allow you to mix both declarations and usage in a single line, like:
Code:
`int *p = &x;`
But this is the same as:
Code:
```int *p;
p = &x;```
Why differenciate between declarations and usage? Because that asterisk in int *p; is you telling the compiler that p will be used to hold an address an int. While, in usage, doing something like *p = 1; is you talking about an expression using 2 operators: * (for indirection) and = (for assignment). In this usage you are telling * (as indirection) is "access the data at the address inside the variable p"... Nothing to do with the * in the declaration of p...

When you declare:
Code:
`int **pp;`
You are telling the compiler that the variable pp is a pointer (i.e, will hold an address), but, when using pp, using a single * operator, you will get another address (not the int data) which, in turn, points to the data. So, if you declare:
Code:
```int x = 5;
int *p = &x;
int **pp = &p;```
pp will hold the address of the variable p (which is a pointer). The expression *p will access memory where the data of x is, and the expression *pp will access the address where p is... **pp will access the data where x is as well, but just because pp points to p and p points to x.

All this sounds very complicated, here's a practical example. Suppose you want to change an argument passed to a function, inside this function. You can do something like this:
Code:
```void f(int *p) { (*p)++; }
...
int x = 1;
f(&x);
// here x will be 2```
But, suppose you want to change an argument, which is a pointer! The principle is the same, you pass a pointer to a pointer! As in:
Code:
```int reallocateMemory( void **pp, size_t size )
{
// tries to reallocate memory (could return NULL if error).
void *p = realloc( *pp, size );

// If everything is OK, change the pointer!
if ( p )
*pp = p;

// Return a boolean informing the status of this operation (0 = error, 1 = ok).
return p != NULL;
}```
To use this:
Code:
```int *p = NULL;

if ( ! reallocateMemory( &p, 1000 ) )
{ ... error handling ... }```
Notice that &p will not be NULL (p is NULL, not the address of p!), we are getting the address-of p here.

Well... I hope this helps...

PS: Yeah, yeah... for the purists: I know there are some not-so-precise concepts, expressed here, accordingly to the ISO 9989 standard. My intent is to clarify concepts, not the standard... 4. Thanks a lot Niccolo!!!
I read everything, you've been very clear.

Question number 1
When you wrote: Originally Posted by Niccolo Now, in closing, this is a crash:

Code:
```int a = 5;
int b = 4;

int *pointer = NULL;
int **dpointer = &pointer; // this is ok but be warned what's next

**dpointer = 3; // this crashes because pointer itself is NULL.

*dpointer = &a; // this does the same as pointer = &a

**dpointer = 2; // this would work if it hadn't crashed above```
Why is it wrong to write
**dpointer=3;
?
I guess it is a legal expression, because **dpointer is declared as pointer to a pointer to a int.
So, why does it crash?

Question number 2:

You explained that if I have

Code:
```int b=5;
int **dpointer;```
It is not legal to write
Code:
`*dpointer=b;`
because dpointer is a pointer to a pointer (declaration), so it has not sense to write that.
BUT, what if I consider a pointer to a record?

I give you an example immediately.

Let's consider
Code:
```typedef struct list{ //I create a new kind of data

float value;
struct list *next_ptr;
}lista;```
Now let's assume that I created some of these records (with malloc function), and I want to point with a doublepointer to the data the record I created.

Code:
```float d=5;
list *pointer;
list **doublepointer; //I declare a pointer to this record
(*doublepointer)->value=d;
(*doublepointer)->next_ptr=pointer;```
Why in this case is it correct to write
(*doublepointer)->value=d;
? 5. Originally Posted by flp1969 Well... I hope this helps...
It does flp1969, thank you!!!
If you want, take a look to the answer I gave to Niccolo 6. Originally Posted by letthem It does flp1969, thank you!!!
If you want, take a look to the answer I gave to Niccolo
Notice, in Nicolo example, pointer is initialized with NULL (0). Any indirection to a NULL address will crash (segmentation fault).
dpointer holds the address of pointer, and, if pointer is initialized with NULL, *dpointer will give you NULL, and **dpointer will try to access a NULL address...

I think you're having some dificulty grasping the concept of a pointer... Again: A pointer variable is a "normal" variable which holds an memory address. It exists to be used with * operator (or ->, in case of pointers to structures). If you don't initialize the variable, the address which is pointed is "undefined" and probably will get you a segmentation fault... 7. I recommend (seriosly, not a joke) you draw, like this:

In the figure code 1 is:
Code:
```int x = 5;
int *p = &x;
int **pp = &p;```
And code 2 is:
Code:
```int x = 5;
int *p = &x;
int **pp;``` When you have *p, in an expression, you are getting the contents pointed by p (the contents of x)... *pp you'll get contents of p... and **pp you'll get the contents of x (like in *(*p)).

But, in code 2, pp isn't properly initialized, so **pp will crash your program.

Notice: There is no "double pointer", but double "indirection"... A pointer always points to a single object in memory. But it can point to another pointer... 8. I can't do better than @flp1969 at question 1. My point in presenting the illustration was to get you thinking about two separate levels implied by the use of such pointers. There is the compile time level, which you're asking about. Then, there's the run time level, which this example introduced to you. Indeed, the expression **dpointer = 3 is legal and fine at compile time, but the compiler isn't "thinking" about run time. It so happens that at that point no storage has been configured for that integer, because *dpointer is NULL (0).

As to this:

Code:
```float d=5;

list *pointer;

list **doublepointer; //I declare a pointer to this record

(*doublepointer)->value=d;

(*doublepointer)->next_ptr=pointer;```
In this exact code, no storage has been arranged. It is left uninitialized, though your comment hints you might have assigned something not written, I can't say that's true.

However, the compile time formation of "(*doublepointer)->value" is a double de-reference. This is because (*doublepointer) is a pointer to a list, like pointer. If pointer were assigned to a correct memory location for a list instance, "pointer->value" is a way of writing "the value member of the list pointer points to". Put another way, it's like "(*pointer).value". To that end, if doublepointer is pointing to a valid "pointer", itself properly pointing to an instance of "list", then "(**doublepointer).value" is the same as "(*pointer).value", which is the same as (*doublepointer)->value which is the same as "pointer->value".

The "->" operator is a dereference to member. (*pointer) is a dereference of the pointer (which is, then, the instance). If "list l;" instantiated a list as "l", and pointer = &l, and doublepointer = &pointer, then l.value is the same as (*pointer).value and (**doublepointer).value and pointer->value and (*doublepointer)->value. 9. Originally Posted by flp1969 Notice: There is no "double pointer", but double "indirection"... A pointer always points to a single object in memory. But it can point to another pointer...
Thank you flp1969, you've been very clear!! 10. Originally Posted by Niccolo However, the compile time formation of "(*doublepointer)->value" is a double de-reference. This is because (*doublepointer) is a pointer to a list, like pointer. If pointer were assigned to a correct memory location for a list instance, "pointer->value" is a way of writing "the value member of the list pointer points to". Put another way, it's like "(*pointer).value". To that end, if doublepointer is pointing to a valid "pointer", itself properly pointing to an instance of "list", then "(**doublepointer).value" is the same as "(*pointer).value", which is the same as (*doublepointer)->value which is the same as "pointer->value".
Great Niccolo, I was confused about the use of pointers, double pointers and structures.
Thanks to you, flp1969 and the immortal "Kernighan Ritchie", I've understood what was missing! Popular pages Recent additions double, equal, pointer, pointers, question 