I was iterating a tree data structure which has a pointer to its root as follows-
struct node *root;
when I have to pass reference of this root as a parameter to a function.... I have to pass it like-
calcHeight(&root);
-
-
-
//somewhere
int calcHeight(struct node **root) // function defination is this
My question is- why do we need to pass "root" pointer as &root? can't we just pass root like--
struct node *root;
calcHeight(root);
int calcHeight(struct node *root);
// EDIT
void someFunct(int *arr){
printf("arr2 inside someFunct is %d\n",arr[2]);
arr[2]=30;
}
int main()
{
int *arr=(int*)calloc(10,sizeof(int));
printf("arr[2] is %d\n",arr[2]);
someFunct(arr);
printf("arr[2] finally is %d\n",arr[2]);
return 0;
}
In this case arr
in main function is modified even when I'm not passing the address of arr.
I'm getting the fact that for structures and single value vars we HAVE to pass the address like someFunct(&var)
but this is not necessary for arrays? for arrays we write someFunct(arr)
But I'm not getting the reason behind this?
struct node *
is a pointer to a struct node
.
struct node **
is a pointer to a pointer to a struct node
.
The reason for passing in a struct node **
could be that the function needs to modify what the struct node *
is actually pointing at - which seems odd for a function named calcHeight
. Had it been freeNode
it could have made sense. Example:
void freeNode(struct node **headp) {
free(*headp);
*headp = NULL; // make the struct node * passed in point at NULL
}
Another reason could be to make the interface consistent so that one always needs to supply a struct node **
to all functions in the functions supporting struct node
s - not only those actually needing to change what the struct node *
is pointing at.
Regarding the added // EDIT
part:
In this scenario there is no reason to send in a pointer-to-pointer. If you do not need to change the actual pointer, you only need to send in the value of the pointer.
Example memory layout:
Address What's stored there
+-----+
| +0 | uint64_t ui1 = 1 <--+
+-----+ |
| +8 | uint64_t ui2 = 2 |
+-----+ |
| +16 | uint64_t* p = &ui1 ---+
+-----+
Now, if a function only need an uint64_t
value, you can send in ui1
, ui2
or *p
to that function.
void someFunc(uint64_t val) { ++val; ... }
The changes this function makes to val
are not visible to the caller of the function.
If a function is supposed to be able to make changes that are visible to the caller of the function, send in a pointer:
void someFunc(uint64_t *valp) { *valp = 10; }
Calling it with someFunc(&ui1);
or someFunc(p);
will change ui1
and assign 10 to it.
If you have a pointer and want to change what it's actually pointing at, which is what your original question was asking, you would need to send in a pointer to that pointer:
void someFunc(uint64_t **valpp) { *valpp = &ui2 }`
If you call that with someFunc(&p)
(where p
is currently pointing at ui1
) you will find that after the function call, p
will point at ui2
:
+-----+
| +0 | uint64_t ui1 = 1
+-----+
| +8 | uint64_t ui2 = 2 <--+
+-----+ |
| +16 | uint64_t* p = &ui2 ---+
+-----+