-
Pointers to Pointers
okay guys, here goes...
I am looking at this example code I downloaded...
-------------------------------------------------
Code:
struct sample **kam = NULL;
void sample_init (struct sample *kam)
{
kam->window=0;
kam->photo=0;
}
---------------------------------------------------
Now, kam is declared as a pointer to a pointer of structure sample.
So far, so good.
But, in the function declaration of sample_int, we now find kam again, but this time being declared and passed as only a pointer to structure sample.
I don't think this sample is correct. How can kam be a pointer to a pointer and also just be a pointer? Kam can only hold one address, but not two right? Isn't this example wrong?
-
It's not wrong. The first definition of **kam is at a global scope. Any function can use it. The second definition of kam is at a scope local to the function sample_init(). Concequently, this function can use only it's own redefined "* kam". Similarly, no other function can use *kam.
Not wrong, just misleading :)
-
>Isn't this example wrong?
No, but it is incredibly confusing and considered bad style. Just because the most nested variable hides all others of the same name doesn't mean you should do so.
-
clarification
Thanks. I see what you mean.
So, let me get this straight. We have this structure 'sample'....
...and we have globally declared "kam", which holds the address of some mystical pointer....which points to the structure 'sample'.
And then we have "kam" (same name but not the same as above) in a local scope to a function. And it is a pointer to the structure 'sample'.
So writing this out sort of as a diagram, we have...
**kam ----> "some mystical pointer" -------> struct 'sample'
*kam ----------------------------> struct 'sample'
So, the only thing common here is the structure 'sample'. What purpose then is **kam, since everything we need to do with the structure 'sample' can be done through *kam?
-
>...and we have globally declared "kam", which holds the address of some mystical pointer....which points to the structure 'sample'.
Not quite. The global kam points to NULL, so there's nothing mystical about it and it doesn't reference valid memory.
>So writing this out sort of as a diagram, we have...
If the global kam were pointed to something valid, your diagram would be correct.
>What purpose then is **kam, since everything we need to do with the structure 'sample' can be done through *kam?
Without knowing the context of the program I can't say, but double pointers are usually used for dynamic matrices:
Code:
// Working with the global kam
kam = malloc ( M * sizeof *kam );
for ( i = 0; i < M; i++ )
kam[i] = malloc ( N * sizeof *kam[i] );
This creates an MxN matrix of sample instances.
-
Hmmmm....
You must be right.
Looking at this code I see the following:
Code:
int main (int argc, char **argv)
{
kam = malloc (sizeof (struct sample *)*2);
kam[0] = malloc (sizeof (struct sample ));
sample_init( kam[0] );
kam[1]=NULL;
}
So, this is a way of creating some kind of array matrix? I have never seen a matrix created like this.
-
>I have never seen a matrix created like this.
Yes, for when you need an array, but you don't know the size at compile time.
-
okay, I guess what seems odd is the code never defined any arrays.
It's just out of the blue appears this 'kam[0]' and 'kam[1]'. I'm no where near an advanced 'C' programmer, but there's no declaring of an array anywhere...unless this is some advanced way of creating an array of pointers without using the syntax for arrays I normally see. (???)
-
I suppose what is happening here is that when I am seeing kam[0] and kam[1], I am looking at the declaration of the array and assigning its value at the same time.
kam is a global pointer to a pointer.
Then kam is assigned its value within main.
Next, kam[0] creates pointer to pointer array element zero and makes an assignment.
Next, kam[1] creates pointer to pointer array element one and makes an assignment.
I think it is sloooooooooowly sinking in.
-
>I guess what seems odd is the code never defined any arrays
You can do perform two operations with arrays as a whole: take an array's address and use an array as the operand for sizeof. Everything else converts an array name to a pointer to the first element. So subscripting under the syntactic sugar is:
Code:
*( a + i ); /* Equivalent to a[i] */
You can use subscripting with pointers provided the memory allocated to those pointers allows it. Because of this feature, it's trivial to simulate dynamically sized arrays at runtime using pointers.
The similarities between arrays and pointers is an endless well of confusion for beginners and experienced programmers alike.
-
ouch! My brain hurts.
Well, I guess it's time to get my scuba gear on and jump into that well.
Thanks Prelude!