pointers don't change after i modified it - c

I'm setting up a struct called Node
typedef struct node{
struct node *left;
struct node *right;
struct node *parent;
}node;
and a function that operate on the nodes:
int test(node *old,node* new){
old->parent->right = new;
new->parent = old->parent;
}
Ok, so i make 3 nodes and set up the relationship between them
node* me =malloc(sizeof(node));
node* me1 = malloc(sizeof(node));
node* me2 = malloc(sizeof(node));
me->right = me1;
me->left = me2;
me1->parent = me;
me2->parent = me;
test(me1,me);
1.However, after test(), me1->parent->right changed while me1 didn't, which is weird because me1 and me1->parent->right point are the same address. I wonder if i make any wrong assumption here?
2.In function test(), if i replace old->parent->right with old only, then after the function call, the node me1 remains the same. Isn't the pointer modified after we do operations on it inside a function,and why in this case it is not?

me, me1, and me2 are local variables inside your outer function (let's assume it was main). These pointers are never modified, so after the call to test, me1 still points to the same node as before, while the pointer me1->parent->right now points to me. So, "me1 and me1->parent->right point are the same address" isn't true anymore!
If you only modify old inside test, you will only modify the parameter old, which is a copy of me1. After test returns, this copy is forgotten, and the modification has no effect. If you want to modify the me1 variable from within test, you will have to pass a pointer to the pointer, i.e. a double pointer:
int test(node **old,node* new){
*old = new;
...
}
and call it as test(&me1,me);.
Also: Please don't name things "new", because if you ever decide to compile the code as C++, this will conflict with the reserved keyword new.

Here is what your test() method does:
int test(node *old,node* new){
old->parent->right = new;
new->parent = old->parent;
}
when you call this:
me->right = me1;
me1->parent = me;
test(me1,me);
These steps happens:
me1's parent is me and me's right is me1. So me's right becomes me again.
me's parent becomes me itself.

Related

what does this struct node **p is doing?

I am learning data structure, and here is a thing that I am unable to understand...
int end(struct node** p, int data){
/*
This is another layer of indirection.
Why is the second construct necessary?
Well, if I want to modify something allocated outside of my function scope,
I need a pointer to its memory location.
*/
struct node* new = (struct node*)malloc(sizeof(struct node));
struct node* last = *p;
new->data = data;
new->next = NULL;
while(last->next !=NULL){
last = last ->next ;
}
last->next = new;
}
why we are using struct node **p?
can we use struct node *p in place of struct node **p?
the comment which I wrote here is the answer I found here, but still, I am unclear about this here is the full code...
please help me
thank you
Short answer: There is no need for a double-pointer in the posted code.
The normal reason for passing a double-pointer is that you want to be able to change the value of a variable in the callers scope.
Example:
struct node* head = NULL;
end(&head, 42);
// Here the value of head is not NULL any more
// It's value was change by the function end
// Now it points to the first (and only) element of the list
and your function should include a line like:
if (*p == NULL) {*p = new; return 0;}
However, your code doesn't !! Maybe that's really a bug in your code?
Since your code doesn't update *p there is no reason for passing a double-pointer.
BTW: Your function says it will return int but the code has no return statement. That's a bug for sure.
The shown function (according to its name) should create a new node and apend it at the end of the list represented by the pointer to a pointer to a node of that list. (I doubt however, that it actually does, agreeing with comments...)
Since the list might be empty and that pointer to node hence not be pointing to an existing node, it is ncessary to be able to potentially change the pointer to the first elemet of that list away from NULL to then point to the newly created node.
That is only possible if the parameter is not only a copy of the pointer to the first node but instead is a pointer to the pointer to the first node. Because in the second case you can dereference the pointer to pointer and actually modify the pointer to node.
Otherwise the list (if NULL) would always still point to NULL after the function call.

Pointer to declared but uninitialized variable in C

I've been reviewing the basics of singly linked list In C with materials from Stanford CS Library, where I came cross the following code:
struct node{
int data;
struct node* next;
};
struct node* BuildWithDummyNode(){
struct node dummy;
struct node* tail = & dummy; // this line got me confused
int i;
dummy.next = NULL;
for (i=1;i<6;i++){
Push(&(tail->next), i);
tail = tail->next;
}
return dummy.next;
}
Probably not revenant, but the code for Push() is:
void Push(struct node** headRef, int data){
struct node* NewNode = malloc(sizeof(struct node));
newNode->data = data;
newNode->next = *headRef;
*headRef = newNode;
}
Everything runs smoothly, but I've always been under the impression that whenever you define a pointer, it must point to an already defined variable. But here the variable "dummy" is only declared and not initialized. Shouldn't that generate some kind of warning at least?
I know some variables are initialized to 0 by default, and after printing dummy.data it indeed prints 0. So is this an instance of "doable but bad practice", or am I missing something entirely?
Thank you very much!
Variable dummy has already been declared in the following statement:
struct node dummy;
which means that memory has been allocated to it. In other words, this means that it now has an address associated with it. Hence the pointer tail declared in following line:
struct node* tail = & dummy;
to store its address makes perfect sense.
"But here the variable "dummy" is only declared and not initialized."
The variable declaration introduces it into the scope. You are correct in deducing it's value is unspecified, but to take and use its address is well defined from the moment it comes into scope, right up until it goes out of scope.
To put more simply: your program is correct because you don't depend on the variables uninitialized value, but rather on its well defined address.

Why doesn't my code work when I want to append something to be head of the linked list?

void addToHead(Node *list, Node added)
{
// Where NodePointer is a typedef of a pointer to a node
(*added).next = (*list);
(*list) = added; //Set list pointer back to first entry
}
For some reason, I'm having issues with this. Why doesn't it work? I thought adding a pointer to a pointer will allow me to change the address of a pointer (as I did with Node * list)
It's hard to say what you're after because I find your question unclear. I'm going to assume that Node contains a Node* next (pointer to Node) because a class or struct cannot contain a full instance of itself and therefor Node.next cannot be a Node.
First, with (*added).next = (*list);. (*list) dereferences a Node* and resolves as a Node, so I'd be surprised if assigning a Node* as a Node would compile.
Second, with (*list) = added;. This one looks more likely to compile, but it will do a shallow copy of added into the space pointed to by list.
No where in your code are you assigning an actual pointer, so I'm confused by what you mean by 'adding a pointer to a pointer'. I also don't know what you mean by 'doesn't work'. You need to explain what behavior you want to see, and what behavior you actually see.
void addToHead(Node * list, Node* added)
{
//Where NodePointer is a typedef of a pointer to a node
(*added).next = list; //you could also do added->next = list
list = added; //Set list pointer back to first entry
}

Double pointer to binary search-tree node

This might seem like a silly question to some of you and I know that I get things mixed up quite often but I need to understand the code so I can stop obsessing about it and focus on the real matter of why I need to use it.
So, in the code I see several assignments like this:
struct bst_node** node = root;
node = &(*node)->left;
node = &(*node)->right;
is there an invisible parenthesis here?
node = &((*node)->right);
This example is taken from literateprograms.org.
So to me it seems &(*node) is unnecessary and I might as well just write node->left instead, but the code seems to work where I can't make sense of it and I'm wondering if it's because I'm misunderstanding what's happening at those lines. Particularly, at one place in the code where it is deleting a node by constantly moving the "deleted" data to the bottom of the tree to safely remove the node without having to "break things", I'm lost because I don't get how
old_node = *node;
if ((*node)->left == NULL) {
*node = (*node)->right;
free_node(old_node);
else if ((*node)->right == NULL) {
*node = (*node)->left;
free_node(old_node);
} else {
struct bst_node **pred = &(*node)->left;
while ((*pred)->right != NULL) {
pred = &(*pred)->right;
}
psudo-code: swap values of *pred and *node when the
bottom-right of the left tree of old_node has been found.
recursive call with pred;
}
can keep the tree structure intact. I don't understand how this makes sure the structure is intact and would appreciate some help from somebody who knows what's going on. I interpret node being a local variable on the stack, created at the function call. Since it is a double pointer it points to a location in the stack (I assume this, since they did &(*node) previously to the function call), of either it's own stack or the function before, which then points to said node on the heap.
In the example code above what I think it is supposed to do is switch either left or right, since one of them is NULL, and then switch the one that isn't (assuming the other one isn't NULL?) As I said, I'm not sure about how this would work. My question mostly relates to the fact that I think &(*node) <=> node but I want to know if that's not the case etc.
node = &(*node)->right;
is there an invisible parenthesis here?
node = &((*node)->right);
Yes. It is taking the address of the right member of *node. The -> takes precedence over &; see C++ Operator Precedence (-> is 2 and & is 3 in that list) (it's the same general precedence as C).
So to me it seems &(*node) is unnecessary and I might as well just write node->left instead,
Your premise is off. There is no expression &(*node), as explained above, the & applies to the entire (*node)->left, not (*node).
In that code the double pointers are just that, a pointer to a pointer. Just as this works:
int x = 0;
int *xptr = &x;
*xptr = 5;
assert(x == 5);
This is the same, it changes the value of the pointer x:
int someint;
int *x = &someint;
int **xptr = &x;
*xptr = NULL;
assert(x == NULL);
In that code snippet you posted, assigning a pointer to *node changes the value of the pointer that node points to. So, e.g. (pseudo-ish code):
typedef struct bst_node_ {
struct bst_node_ *left;
struct bst_node_ *right;
} bst_node;
bst_node * construct_node () {
return a pointer to a new bst_node;
}
void create_node (bst_node ** destination_ptr) {
*destination_ptr = construct_node();
}
void somewhere () {
bst_node *n = construct_node();
create_node(&n->left); // after this, n->left points to a new node
create_node(&n->right); // after this, n->right points to a new node
}
Noting again that &n->left is the same as &(n->left) because of precedence rules. I hope that helps.
In C++ you can pass arguments to a function by reference, which is essentially the same as passing a pointer except syntactically it leads to code that is a bit easier to read.
That is useful
&(*node)->left <=>&((*node)->left)
The variable edited by this code is *node. I need the context fo this code to give more info

Segmentation fault when passing double pointer and pointer to function

When I do:
t_node *node1;
t_node **head;
void *elem;
int c = 1;
elem = &c;
head = NULL;
node1 = malloc(sizeof(t_node));
node1->elem = elem;
head = &node1;
//add_node(node1,head); //substitute this with line above and it doesn't work
printf("%d\n",*(int*)(*head)->elem); // prints 1 and works fine
BUT WHEN I CREATE A FUNCTION CALLED ADD_NODE IT DOESN'T WORK?!??!?
void add_node(t_node *node1, t_node **head){
head = &node1;
}
this doesn't make any sense to me... why would this cause this to not work? calling the function literally does the same exact code.
EDIT: Keep in mind the signature of the add_node is not under question. it is required of me to have that signature
C is a pass by value language. Your function actually doesn't do anything at all as far as main() is concerned.
Check out this question in the comp.lang.c FAQ.
In the call to the function the parameters have a scope that is only of that function, so your assignment of 'head = &node1' has no affect to variables outside the function.
To affect the variables you passed in, you must pass the address of the variables. Eg:
void add_node(t_node **node1, t_node ***head){
*head = node1;
}
and the call would be:
add_node(&node1, &head);
Note that you must dereference the 'head' pointer in the function so the value at 'head' would be updated with the 'node1' value.
in 'C' varaibles are passed by reference, so to change the value in function call you should pass the pointer to variable.
correct step would be -
void add_node(t_node **node1, t_node ***head){
*head = node1;
}

Resources