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
}
Demo
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 nodes - 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 ---+
+-----+
Because in calcHeight you're passing your argument by value. If you want to modify the pointed value by root you need to pass the adress of the pointer.
First one is a pointer to node which is a structure.
struct node *root;
defines root as a variable which can store the address of a node.
Second one is a pointer to a pointer to node which is a structure.
struct node **root;
defines root as variable which can store address of another variable which has the address of a node.
why do we need to pass "root" pointer as &root?
calcHeight(&root);
C passes arguments by value, not by reference. so, you have to pass the address of root to modify the value of root.
Related
I'm trying to delete nodes from a simply linked list on C, when I delete any other node except the first it works fine, but when I try to delete the first node the whole list messes up, I've tried different solutions and I have the same outcome, I don't know what to do anymore
One of my tries was this:
void deleteClient (client **p, int n){
client *t = *p;
if (t){
while (t && t->id != n)
t = t->next;
if (t){
client * ax = t;
t = t->next;
free(ax);
}
}
}
The other one was this
void deleteClient (client **p, int n){
client *t = *p;
if (t)
if (t->id == n){
client * ax = *p;
*p = (*p)->next;
free(ax);
return;
}
else{
while (t->next && t->next->id != n)
t = t->next;
if (t->next){
client * ax = t->next;
t->next = t->next->next;
free(ax);
}
}
}
But in both versions of the code it only deletes fine from the second node onwards, while messing up the whole list if I try to delete the first node.
You can eliminate testing for multiple cases (is node the 1st, if not the 1st, etc..) by simply using a pointer-to-pointer to node to hold the current node and a pointer to the next node, e.g.
/** delete node with value n from list (for loop) */
void deleteClient (client **p, int n)
{
client **ppn = p; /* pointer to pointer to node*/
client *pn = *p; /* pointer to node */
for (; pn; ppn = &pn->next, pn = pn->next) {
if (pn->id == n) {
*ppn = pn->next; /* set address to next */
free (pn);
break;
}
}
}
This approach is detailed in Linus on Understanding Pointers
The first question that comes to me, when dealing with your problem is: If you have defined an interface to your function that receives a pointer to a client by reference, why don't you get profit from that fact and use it to modify the received pointer? (I was astonished about this, because the first thing you do, in the function is to dereference it, and use a normal pointer, and you don't touch the original pointer received anymore) If you pass a pointer to the first node, you'll never have access to the pointer variable, and you'll not be able to change its value, and so, you'll never be able to unlink the first element, and it is because of that, that you need to access the pointer pointing to the first node (in order to be able to change it). Very good at passing the pointer by reference, but bad as you didn't know why.
(pointer to 1st el.)
+-----+ +----------------+ +----------------+
--->| *p >---------->| client | next >------->| client | next >------.
+-----+ +----------------+ +----------------+ |
^ V
| NULL
+--|--+
| p | (reference to the pointer that points to the first element)
+-----+
As you move the pointer reference, you get up to this scenario:
+-----+ +----------------+ +----------------+
--->| *p >---------->| client | nxt >-------->| client | nxt >-------.
+-----+ +----------------+ +----------------+ |
^ V
,-----------------------' NULL
+--|--+
| p | (see how the reference points to the pointer, not to client node)
+-----+
From this scenario, with a reference pointed by &p, we need to make the value pointed by the pointer referenced to the next client node's nxt pointer, and not to the node itself. As here:
,---------------------------.
| |
+-----+ | +----------------+ | +----------------+
--->| *p >----' | client | nxt >-----+-->| client | nxt >-------.
+-----+ +----------------+ +----------------+ |
^ ^ =====
| | ===
+--|--+ +-|--+ =
| p | | q | (q points to the client node, instead)
+-----+ +----+
In this graph, q is a node pointer we use to link to the client node we are going in order to free() after it has been unlinked. So, your first approach can be turned into this:
void deleteClient (client **p, int n)
{
/* first advance the reference to the n-esim pointer,
* (zero meaning the first node) We decrement n after
* checking, and test goes on while *p is also non null
*/
while (*p && (*p)->id != n)
p = &(*p)->next; /* move the reference to a reference
* to the pointer in the next node. */
client *q = *p; /* temporary link to the node to be
* freed */
if (q) { /* if found */
*p = q->next; /* make *p point to the next node. */
free(q); /* free the client node */
}
}
The way to call this routine should be:
client *list;
/* ... */
deleteClient(&list, 3); /* delete node with id == 3 */
The statement p = &(*p)->next; needs some explanation:
*p is the address of the client node that the pointer referenced by p points to.
(*p)->next is the next pointer of the node the pointer referenced by p points to.
&(*p)->next is the address of that pointer.
So we make p to point to the address of the next pointer of the client node pointed to by the referenced pointer *p.
NOTE
The reason your code messes up the whole list when you delete the first node is that you make the pointer (the initial pointer to the first node) to point to the second, but that pointer is local to your function and, as you never modify the pointer passed by reference (you modify the copy you make as soon as you get into the function, it is never modified above it), it continues to point to the (now free()d) node, so this makes the mess (not only you have a pointer pointing to an invalid address, you have leaked the rest of the nodes ---as the next field of the pointed node can have been changed by free() as a result of managing the returned memory chunk---) :)
Finally, you have a complete example here, that you can checkout from github.
Code to my linked list program: This is the code I saved on github
Knowing that pointers always accept the address of a variable. So if someone is writing just the name of array means that that is the address of the first element of the array. Ok that is right that's the address so we need not write an & in front of the array name. But if it were any other thing then we had to use the & sign. So in case of int we write that & sign in front of it. But what in the case of structure that is also a kind of variable of some custom made size?
The code for array may look like this:
int arr[] = {34,234,6234,346,2345,23};
int i;
for(i=0; i<(sizeof(arr)/arr); i++)
int *pointer = arr+i; //Now pointer can point to all the member array one by one
The code for an int may look like this:
int a = 5;
int *pointer = &a;
But if i have two pointers(head & temp) to structure of type struct node. Now I am writing the code for node.
struct node {
int data;
struct node *next; // this is pointer to next element in the Linked List
};
Now initially head is NULL i.e. not pointing to anything
head = NULL;
But on the first insertion to the linked list if do this:
head = temp; // both are pointers
knowing that head can only take the address coz its a pointer but temp is not an array so if write this writing temp doesn't mean its the address of that structure temp
Should I do this
head = &temp
to actually get the address of that temp structure(pointer)?
I get a feeling that we do head = temp and that valid cause like arrays temp is pointer of type structure node. So writing temp means just the address of the temp pointer in the memory. And Now head pointer is having the address of temp & pointing to what head has?
Is head pointing to address of temp or head has now address of temp. Pointing and having are different I guess.
To explain my comment, see the following crude drawings:
In the case of head = temp it will look something like
+------+
| temp | --\
+------+ \ +----------------+
>--> | your structure |
+------+ / +----------------+
| head | --/
+------+
That means that both head and temp points to the same place.
If you on the other hand do head = &temp (and the compiler allowed it), it will look like
+------+ +------+ +----------------+
| head | ---> | temp | ---> | your structure |
+------+ +------+ +----------------+
That is, head points to temp and not to your structure.
head and temp both are of type struct Node*. Assigning temp to head means head is pointing to the same location as that of pointed by temp. &temp is the address of the temp variable which is of pointer to struct NODE type, i.e struct Node**.
temp and &temp both are of different type. You compiler should raise awarning fo the assignment
head = &temp; // assigning incompatible pointer without cast
In case of single variable whether an int or char the address of operator & is used to reference that variable. In case of an array of integers, the name of the array arr[] i.e arr itself represents the address of the first element of the array. See below how the pointer arithmetic operation arrays internally do:
To reference the 'i'th element we write arr[i] = *(arr + i)
So, arr[0] = *(arr + 0) = *(arr)
But in your case, head and temp are pointers of the type struct node*. Using & operator to assign the address of temp to head will firstly won't be allowed by the compiler giving a cast error and moreover it will not serve your purpose either. What you should do is head = temp which will make head and temp point to the struct node.
I was writing some C-code to implement basic Stack data structure operations like push,pop,etc.
I'm using the Linked List implementation of the stack.
In this implementation, every time I push a value into the stuck, I create a new node, and set it as the head node of my Linked List. So this involves changing the references of the head node.
void push(stack **t, int ele)
{
stack *new, *temp;
temp=*t;
new=(stack *)malloc(sizeof(stack));
if(new==NULL)
{
printf("\n stack overflow");
return;
}
new=(stack *)malloc(sizeof(stack));
new->val=ele;
new->next=*t;
*t=new;
}
If I were to write a similar code using single pointers, then it would be like this
void push(stack *t, int ele)
{
stack *new, *temp;
temp=t;
new=(stack *)malloc(sizeof(stack));
if(new==NULL)
{
printf("\n stack overflow");
return;
}
new=(stack *)malloc(sizeof(stack));
new->val=ele;
new->next=t;
t=new;
}
In the function, the head node(**t) appears on the RHS of assignment in all steps but this
*t=new;
Basically the first code assigns 'new' to the pointer of **t, that is *t, and the second code assigns 'new' to the pointer of *t, that is t.
Both seem to be requiring only the single pointer to the head node to be assigned as 'new', yet only the first code works, and second doesn't actually modify the head node value.
What is the explanation for this to happen? Why doesn't the second code work in a similar way to the first?
Because everything in C is passed by value. So, if you need to assign a new value to an argument to a function, you must add a level of indirection. if you don't you simply receive a local copy, so any value assigned to that copy will be visible only within the function itself.
On a side note, don't cast the return value of malloc in C. It is unnecessary, clutters you code, and can hide an error for compilers which allow default int.
On.. another side note, instead of writing something like:
new_stack = malloc(sizeof(stack));
Use this instead:
new_stack = malloc(sizeof(*new_stack));
Now you don't have a problem if the type of new_stack ever changes.
In case of single pointer say
int addInBeginning(int *s)
{
... // add a node in the beginning of the linked list
}
int main()
{
int *t;
... // make t point to a linked list say t ---> 1 -> 2 -> 3
f(t);
}
Initially, s and t point to the same list. But when we add a node in the beginning, s points to the new node while t still points to the node it was earlier pointing to. When push returns, the new node is inaccessible from t.
0 -> 1 -> 2 -> 3
^ ^
| |
s t
In case of double pointer, s will point to t which in turn points to the list. So all pointer manipulations happen on the original pointer t.
s ----> t ----> 0 -> 1 -> 2 -> 3
I have a problem understanding this structure , would love to get a clear explanation.
typedef struct exp{
int x;
struct exp *parent;
struct exp **children;
}
what does it mean the parent and the children ?
"parent" is an array of this structure?
and what is the meaning of the children ? it's an array of arrays?!
I really can't understand..
and last thing, If I'm adding an element , it becomes a specific child of some parent, how can I reach all the children of a parent? shouldn't it be a structure "List" (using next etc .. ? )?
thank you!!
This image shows a possible scenario:
It was obtained using this code and DDD
#include <stdio.h>
#include <stdlib.h>
struct exp{
int x;
struct exp *parent;
struct exp **children;
};
int main ()
{
struct exp *x = calloc(1, sizeof(x[0]));
x->x = 42;
x->parent = calloc(1, sizeof(x[0]));
x->children = calloc(5, sizeof(x->children[0]));
x->children[0] = calloc(1, sizeof(x[0]));
x->children[2] = calloc(1, sizeof(x[0]));
x->children[3] = calloc(1, sizeof(x[0]));
x->children[4] = calloc(1, sizeof(x[0]));
return 0;
}
Basically, the children field is a vector of pointers to struct exp. You decide how many elements to put there and the other things.
PS: Code is only a demo, it has not quite a good quality.
It's a pointer to a pointer, which in that case seems to be used as a list of struct exp.
Each struct exp has a reference to it's "parent", and a pointer to a list of children struct exp.
typedef struct exp{
int x;
struct exp *parent;
struct exp **children;
} element;
// create ROOT elemnt
element * root = (element*) malloc(sizeof(element)); //alocate mem. for 1 element
Once we have a "root" we can add children, following is pseudo-code
for 1 to 10{
child = new element;
child->parent = root; // tell the child who is his parent
addToRoot( root , child); // call a function that inserts elemnts to root
}
So now we should have root with a list of 10 elements:
_______________ _______________
| | (children) | | - (parent) points to struct exp, root
| root | - points to list of struct exp -> | child 0 |
| | | | - (children) points to null; // if it's empty
_______________ _______________
_______________
| | - (parent) points to struct exp, root
| child 1 |
| | - (children) points to null; // if it's empty
_______________
_______________
| | - (parent) points to struct exp, root
| child 2 |
| | - (children) points to null; // if it's empty
_______________
_______________
| | - (parent) points to struct exp, root
| child 3 |
| | - (children) points to null; // if it's empty
_______________
.
.
.
_______________
| | - (parent) points to struct exp, root
| child 9 |
| | - (children) points to null; // if it's empty
_______________
Something like that... Did it help?
It's an array of pointers to child nodes- this looks like some kind of tree structure.
There is a parent node for each node, and each node has one or more children. You can travel from a parent to one of its children with
expInstance->children[i];
Where i is a number indicating one of the child nodes. It's not really clear how many child nodes there are from this definition- it could be one, or two, or a million. But given that information you could loop through them. Either with
for(i=0; i<NUMBER_OF_CHILDREN_NODES;i++){
expInstance->children[i];
}
if you know the length of the array in advance or the somewhat strange
while(expInstance.children[i++]){
expInstance->children[i];
}
(There are a couple variously clever ways to do this, but there has to be the assumption built into the structure that there will be a null pointer in the last slot of this array in order to terminate it.)
It is hard to say without seeing more code. Are you trying to implement a tree? From this definition, this is what apparent to me:
parent points to the parent node of this structure.
children points to the array of pointers of all its child nodes.
First of all, remember that a structure cannot contain an instance of itself. IOW, you cannot do something like
struct exp {
int x;
struct exp parent;
...
};
The main reason for this is that the struct type is not complete at the point where you try to declare the parent member; since you haven't finished describing the type yet, the compiler doesn't know how big the parent member should be. Not to mention that the parent member would itself have a parent member of type struct exp, which would in turn have a parent member of type struct exp, which would in turn have a parent member of type struct exp, etc., etc., etc., etc. You'd wind up with an object that required an infinite amount of storage.
So you cannot have a member of type struct exp. However, you can have a pointer to an object of type struct exp; you can create pointers to incomplete types, and all struct pointer types have the same size and representation (IOW, struct foo *pf and struct bar *pb will have the same size, even if struct foo and struct bar do not).
So the parent member is (probably) only meant to point to a single instance of type struct exp (each instance of struct exp has one parent). Likewise the children member is (probably) meant to be a single-dimensioned array of pointers to struct exp (each instance of atruct exp can have zero, one, or more children).
Sorry for asking such a stupid question but I am really confused.
struct Amit
{
int a;
struct Amit *link;
}
*start;
Here both *link and *start are used to point to a node of a linked list, but what's the difference between these two and why can't we put *start inside the structure body?
The link is a member of the structure type. Every structure of type struct Amit has one.
The start is a variable of type 'pointer to struct Amit'. At any given time, there can be at most one variable called start visible.
You could put start inside the structure, but it would become a member of the structure (like link), and you would still need to declare variables of the structure type, or pointers to them.
The idea is that each structure on a list except the last contains a link pointer to the next structure on the list. Normally, the last structure on the list has a link pointer that is NULL (0). When searching down a list, you look at the values, and when you need the next item, you follow the link to it, stopping when the link is NULL.
struct Amit *item = start;
while (item != NULL && item->a != value_wanted)
item = item->link;
It is possible to build a circular linked list instead, which has a different stop criterion.
Looking at the comments, and explaining a bit more...
One way to create a list is:
struct Amit root = { 0, NULL };
struct Amit *start = &root;
The variable root is a structure initialized with root.a == 0 and root.link == NULL (or, equivalently, root.link == 0). The pointer variable start points to (stores the address of) root. Given a new node:
struct Amit next = { 1, NULL };
we can add that to the front of the list which start points to:
next.link = start;
start = &next;
A more plausible way to create a list is by dynamically allocating nodes, including the root node. Consistency is crucial because you have to free the dynamically allocated nodes, and having some nodes dynamically allocated and others not is messy. (I'm assuming that function void *emalloc(size_t nbytes); is a cover function for malloc() that never returns a null pointer - so it does the error checking for me.)
// Create the empty list
start = emalloc(sizeof(*start));
start->a = 0;
start->link = NULL;
// Create a node
struct Amit *node = emalloc(sizeof(*node));
node->a = 42;
node->link = NULL:
// Add the node to the font of the list
node->link = start;
start = node;
You'd normally package this stuff up into functions which manage the allocation, initialization and linking of the nodes.
struct Amit *add_node(struct Amit *start, int value)
{
struct Amit *node = emalloc(sizeof(*node));
node->a = value;
node->link = start;
return start;
}
start = add_node(start, 42);
start = add_node(start, 30);
start = add_node(start, 18);
for (node = start; node->link != 0; node = node->link)
printf("Node: %d (%p)\n", node->a, node->link);
Etc.
This basically defines three things:
a struct (don't capitalize it as Struct, by the way)
a member variable within the struct, named link
a variable outside the struct named start
You can reduce the confusion by separating the definition of the struct from the declaration of the start variable, like this:
struct Amit
{
int a;
struct Amit *link;
};
struct Amit *start;
If you rename "link" to "next" it might help you get a better sense of it. A linked list is like a chain - your "start" (or as usually called, the list "head") is the first ring of the chain, and the next ring of the chain is linked to it through your "next" pointer (in your case, your "link" pointer). You know you got to the last item on your chain when there are no other rings (link is NULL).
Start points to the top of the list and is available globally to your program. Whereas link just keeps track of the next item, and is available when referring to a specific 'node'. See this diagram it may help you understand with a visual!
link internally tracks the following item which keeps track of where the next component is as it is not necessarily contiguous the way arrays are.
+------+ +------+ +------+
| data | | data | | data |
+------+ +------+ +------+
| link |---->| link |---->| link |----> NULL
+------+ +------+ +------+
^
|
START (Keep track of the whole list.)
Hope that helps clarify.