changing pointers in functions, c
I'll say in advance that I'm asking about pointers to pointers, so my words may be a bit vague, but try to stay with me :)
I am trying to understand how changing a pointer passed开发者_运维知识库 as an argument takes effect outside the scope of the function. So far this is what I understand: if a pointer is passed as an argument to a function, I can only change what the pointer points to, and not the pointer itself (I'm talking about a change that will take effect outside the scope of the function, as I said). And if I want to change what the pointer is pointing to, I have to pass a pointer to a pointer.
Am I right so far?
Also, I've noticed that when I have a struct that holds some pointers, if I want to initialize those pointers I have to pass the struct
to the initialization function as a pointer to pointer. Is this for the same reason?
You are right in the first bit but if you've allocated the struct then you can pass a pointer to it. However, if the function allocated the struct, then either you use the function return to collect the value of the newly allocated struct or you pass in a pointer to a pointer in the parameter list.
(I've not got a c compiler to hand but I've tried to write some examples).
- You've allocated the pointer
int main() { struct x *px = malloc(...); initx(px); } void intix(struct x* px){ px-> .... }
- The function allocated the pointer
int main() { struct x *px = initx(); } struct x* intix(){ struct x *px = malloc(...); px-> .... return px; }
- The function allocated the pointer
int main() { struct x *px; initx(&px); } void intix(struct x** ppx){ struct x *px = malloc(...); px-> .... *ppx = px; }
What you should understand is that a pointer is an address. That means that it says "the data for the object is actually there". Therefore you should seperate whether you are changing a variable or changing memory.
When you dereference a pointer and assign to that you are changing memory, not a variable.
int **x;
int **p;
int *q;
box diagram time:
+-----------+ +------+ +-----+
| x (**int) | -> | *int | -> | int |
+-----------+ +------+ +-----+
Say I write to the first box: x = p
+-----------+ +------+ +-----+
| x (**int) | XX | *int | -> | int |
+-----------+ +------+ +-----+
\
\ +------+ +-----+
-> | *int | -> | int |
+------+ +-----+
Say I write to the second box: *x = q
+-----------+ +-----------+ +-----+
| x (**int) | -> | (*x) *int | XX | int |
+-----------+ +-----------+ +-----+
\
\ +-----+
-> | int |
+-----+
In C, the pointers are not very much different from numbers. You can see it as the numerical memory address of something. Next, in C everything is passed as value. This means, if you get a pointer passed to your function, and you change it, you change only your local copy of the pointer. The changes you make to the pointer argument are no going to be visible outside.
Now, what if I want the function to actually change something? Then I give the address of it to the function! So the function knows the actual location of the information I want it to change, so it can change it. This is the way how it works in C.
Hope this explanation makes the things clearer.
You are right on the first count -- in standard C there are only value parameters, and you must pass a pointer to any outside variable which you wish to modify from within the procedure.
The reason for something like a structure initialization functions wanting a pointer to a pointer vary, but mostly it's just for consistency with similar functions that allocate the structure, or because that particular group of functions (I'm thinking of some M$ interfaces) have adopted this style seemingly just to be more cryptic (or, more probably, so that the same interfaces can be used by a pass-by-reference language).
But be aware that, if a pointer to pointer is asked for, the function may be doing something different that what you've casually assumed.
精彩评论