why two pointers used in structure in c - c

I read those about tree in c:
struct node
{
int key_value;
struct node *left;
struct node *right;
};
/* insert a value to tree */
insert(int key, struct node **leaf)
{
if( *leaf == 0 )
{
*leaf = (struct node*) malloc( sizeof( struct node ) );
(*leaf)->key_value = key;
/* initialize the children to null */
(*leaf)->left = 0;
(*leaf)->right = 0;
}
else if(key < (*leaf)->key_value)
{
insert( key, &(*leaf)->left );
}
else if(key > (*leaf)->key_value)
{
insert( key, &(*leaf)->right );
}
}
I can't understand here: insert(int key, struct node **leaf) why two pointers **leaf, does *leaf ok? I am confused when to use two pointers.pls help, thank you very much!

In insert(int key, struct node **leaf) you are Passing the Address pointed by *leaf by C version of "Pass By Reference". And in insert(int key, struct node *leaf) you are passing the Address pointed by *leaf by Pass By Value method.Note C Parameter are always Passed by Value.
So, In This particular Case it doesn't matter if you use insert(int key, struct node **leaf) or insert(int key, struct node *leaf) both will achieve the same outputs.The only difference in this case is that in insert(int key, struct node **leaf) your passing the address by C version of Pass by Reference and in insert(int key, struct node *leaf) your passing the address by Pass By Value method.
Example Code A,
#include<stdio.h>
struct node
{
int data;
};
void AddFive(struct node **t);
int main()
{
struct node *n = NULL;
n = new node;
n->data = 5;
printf("%d\n", n->data);
AddFive(&n);
printf("%d\n", n->data);
return 0;
}
void AddFive(struct node **t)
{
(*t)->data = (*t)->data+5;
}
Example Code B,
#include<stdio.h>
struct node
{
int data;
};
void AddFive(struct node *t);
int main()
{
struct node *n = NULL;
n = new node;
n->data = 5;
printf("%d\n", n->data);
AddFive(n);
printf("%d\n", n->data);
return 0;
}
void AddFive(struct node *t)
{
t->data = t->data+5;
}
If you notice both Code A and Code B achieve the same output.

It is call by reference . if we have to change the value of *leaf then we should have its address thats why we used two *'s when is for pointer of leaf and other to get address of *leaf.

When you want to change the value of a variable defined in main() through some function. Think what do you do. You send the address of that variable and then using that address, change the content of that variable.
Now, in an example cases, the variable is of int type, so sending the address of that variable would mean in the function, you have to receive it in a variable of type int *
void test(int* var) {
*var++;
}
int main() {
int integer = 1;
test(&integer);
printf("%d", integer);
return 0;
}
To change the value of the variable integer you send the address of that to the function test().
Now take this same situation, and think if you need to change the content of a variable which is itself a struct node *. Then you send the address of that variable, and receive it with a (struct node *)*. Thats what is happening in the example you posted.
You want the changes that is to be made to the leaf variable in the insert() fucntion to reflect in the calling function. For this to take place you send the address and change the content accordingly.

C has only pass by value. If pointer to node struct is used as parameter then any modification to passed pointer will not be seen in the caller function. In that case you have to return a pointer from the function insert. Pointer to pointer is used here to update the pointer passed to function insert.

Case 1:
When you are passing a address of a variable then a single pointer is enough to access the variable
Example:
struct node a;
func(&a); // calling
In the func() definition:
func(struct node *a);
Here a points to the address of node. And we can access a using its address directly.
Case 2:
When you are sending the address of pointer variable:
struct node *a;
func(&a); // calling
Then in the function definition it should use a double pointer:
func(struct node **a);

Related

no effect happening to the program when i am putting r=NULL in function ins()

While working with the pointers we are working on address, right?
So when a struct node pointer n is passed to t(struct node *t=n) and later if t is assigned NULL shouldn't n also become NULL?
ps-: it's a program of a binary tree
#include<stdio.h> //check at third line of ins() function
#include<stdlib.h>
struct node{
int data;
struct node* left,*right;
};
struct node* n(int dat){
struct node *x=(struct node*)malloc(sizeof(struct node));
x->data=dat;
x->left=NULL; x->right=NULL;
return x;
};
void ins(struct node* n,struct node* r){
struct node* t=r,*y=NULL; //ok so when i put r=NULL in this next line should this block of memory go
//r=NULL; //NULL
while(t!=NULL){
y=t;
if(t->data>n->data)
{
if(t->left==NULL)
{t->left=n;
t=NULL;
}
else
t=t->left;
}
else {
if(t->right==NULL){
t->right=n;
t=NULL;
}else
t=t->right;
}
}
}
void inorder(struct node* n){
if(n!=NULL){
inorder(n->left);
printf("%d ",n->data);
inorder(n->right);
}}
void main(){
struct node *a,*b,*c,*d,*e,*f,*g,*h;
a=n(32); b=n(20); c=n(100); d=n(16);
e=n(25); f=n(50); g=n(144); h=n(19);
a->left=b; a->right=c;
b->left=d; b->right=e;
c->left=f; c->right=g;
ins(h,a);
inorder(a);
}```
With struct node* t=r you are creating a new and independent variable t that points to the same location as r (lets call that A).
This means any changes to *r are reflected in *t as they both point to the same location A.
when assigning NULL to r, the t variable still points to location A, but r no longer does.
A small example:
int A = 0;
int *r = &A;
int *t = r;
// *r==0, *t==0, point to same location
*r = 55;
// *r==55, *t==55 (same location)
r = NULL;
// *t==55 (*r is no longer valid as r is NULL)

referenced values are lost with stack frame collapse

I am currently attempting to load values from an array into a stack data structure that I have implemented with a linked list. In my push() function I create each new node in my linked list through the use of a pointer so that they do not disappear when the push() stack frame collapses and control returns to reverse(). However, even though I am passing information through the use of pointers, the item I am referencing appears not be returning, as I keep getting NULL values in the calling function despite getting valid values in the called function. Why is this information not returning to my calling function?
#include<stdio.h>
#include<stdlib.h>
struct Node
{
char data;
struct Node* next;
};
void push(char x, struct Node* tp)
{
struct Node* temp = (struct Node*)malloc(sizeof(struct Node*));
temp->data = x;
temp->next = tp;
tp=temp;
printf("\ntp points to %p", tp);
}
void reverse (char c[])
{
struct Node* tp = NULL;
int i = 0, j = 0;
while (c[i] != '\0')
{
push(c[i], tp);
printf("\ntp points to %p", tp);
i++;
}
}
int main(void)
{
char c[] = {"coolio"};
printf("\n%s", c);
reverse(c);
}
The problem is that push cannot change tp that you pass it from reverse, because tp is passed by value. Change the function to return the value to be assigned to tp, like this:
struct Node* push(char x, struct Node* tp) {
... // your code here
return temp;
}
The call should look like this:
while (c[i] != '\0') {
tp = push(c[i], tp);
printf("\ntp points to %p", (void*)tp);
i++;
}
Note that using %p requires a cast to void*.
Demo.

Creating a binary tree but it doesn't work — tree is always null

I am creating a code to insert the elements in tree, but tinsert function does not insert; what is wrong with my code? I have checked many times but tree is always NULL.
The code has only 2 functions: one to insert, and second to show it in preorder.
#include<stdio.h>
#include<stdlib.h>
struct btree {
int val;
struct btree *left;
struct btree *right;
};
static int c=0;
typedef struct btree node;
void tinsert( node *n,int a)
{
c++;
printf("%d\n",c);
if(n==NULL)
{
n=(node *)malloc(sizeof(node));
n->left=NULL;
n->right=NULL;
n->val=a;
//printf("adding root %d\n",n->val);
//n=temp;
}
else if(a>=(n->val))
tinsert(n->right,a);
else
tinsert(n->left,a);
return ;
}
void preorder_display(node *n)
{
if(n!=NULL)
{
printf("%d\n",n->val);
preorder_display(n->left);
preorder_display(n->right);
}
else
printf("tree is null\n");
}
int main()
{
//int N;
//int num[100];
//int i;
node *ntree=NULL;
tinsert(ntree,4);
tinsert(ntree,6);
tinsert(ntree,8);
tinsert(ntree,1);
printf("tree is \n");
preorder_display(ntree);
return 0;
}
tinsert works on a local copy of your ntree, it doesn't change the one in your main. You can fix it by passing a pointer to it (i.e.: double pointer, pointer to a pointer).
So your tinsert will look like this:
void tinsert( node **n,int a)
And in your main you'll call it like this:
tinsert(&ntree,4);
Of course, you'll need to adjust the code in tinsert to de-reference the pointer and access it correctly.
Or allocate the root node in your main.
you pass your root node ntree to tinsert function by value, so when when the function is done you will stay with original value of ntree which is NULL.
You better rewrite your function, so you will pass pointer to pointer
void tinsert( node **n,int a)
//and invocation is like that :
tinsert(&ntree,4);
when you pass ntree from main to tinsert function,
new copy is created to your node*n;
One way is to make use of pointer to pointer
Or second solution is here:
Here is a solution:
#include<stdio.h>
#include<stdlib.h>
struct btree{
int val;
struct btree *left;
struct btree *right;
};
static int c=0;
typedef struct btree node;
node* tinsert( node *n,int a)
{
c++;
printf("%d\n",c);
if(n==NULL)
{
n=(node *)malloc(sizeof(node));
n->left=NULL;
n->right=NULL;
n->val=a;
//printf("adding root %d\n",n->val);
//n=temp;
}
else if(a>=(n->val))
tinsert(n->right,a);
else
tinsert(n->left,a);
return n;
}
void preorder_display(node *n)
{
if(n!=NULL)
{
printf("%d\n",n->val);
preorder_display(n->left);
preorder_display(n->right);
}
else
printf("tree is null\n");
}
int main()
{
//int N;
//int num[100];
//int i;
node *ntree=NULL;
ntree=tinsert(ntree,4);
ntree=tinsert(ntree,6);
ntree=tinsert(ntree,8);
ntree=tinsert(ntree,1);
printf("tree is \n");
preorder_display(ntree);
return 0;
}
C supports the pass by value only. However, this does not prevent you from modifying the value of a variable from another function, because you can always refer to a variable using it's memory; and in C it's done through pointers, an abstraction representing a memory location.
When you pass a value to the function, the value of the actual parameter is copied to the value of formal parameter. Note that a pointer's value is the address it points to. So, this value is copied into the formal parameter. So the new pointer inside the function points to the exact same location your original variable. You can deference the pointer anytime to manipulate it's value.
Here, you are required to manipulate a pointer. So you pass a pointer-to-pointer to the function:
tinsert(&ntree,4);
In your function, you deference it to get your original pointer; like the following:
void tinsert(node **n, int a)
{
//...
*n = malloc(sizeof(node));
//...
}

Assigning a pointer the address of another pointer

I am very confused as to what the following code means. In somefunction the parameter is a pointer to a struct node. In the main the argument I am putting in is the address location of another pointer called A. So what does that exactly mean? What is the difference between A and B? Do A and B represent the same pointer? Does B now point to C after the line (*B)=C?
struct node{
int value;
};
void somefunction(Struct node *B)
{
struct node *C = (struct node *)malloc(sizeof(struct node));
(*B)=C;
};
main()
{
struct node *A;
somefunction(&A);
}
When you pass by pointer, you want changes made within a function to be visible to the caller:
struct node {
int value;
};
void foo(struct node* n) {
n->value = 7;
}
struct node n;
foo(&n);
// n.value is 7 here
and you pass an address of a pointer when you want to change the pointer itself:
void createNode(struct node** n) {
*n = malloc(sizeof(struct node));
}
struct node* nodePtr;
foo(&nodePtr);
May be this Modified and commented code will help you in understanding.
// Step-3
// Catching address so we need pointer but we are passing address of pointer so we need
// variable which can store address of pointer type variable.
// So in this case we are using struct node **
//now B contains value_in_B : 1024
void somefunction(struct node **B)
{
// Step-4
// Assuming malloc returns 6024
// assume address_of_C : 4048
// and value_in_C : 6024 //return by malloc
struct node *C = (struct node *)malloc(sizeof(struct node));
// Step-5
// now we want to store value return by malloc, in 'A' ie at address 1024.
// So we have the address of A ie 1024 stored in 'B' now using dereference we can store value 6024 at that address
(*B)=C;
};
int main()
{
// Step-1
// assume address_of_A : 1024
// and value_in_A : NULL
struct node *A = NULL;
// Step-2
// Passing 1024 ie address
somefunction(&A);
// After execution of above stepv value_in_A : 6024
return 0;
}

changing struct/variable content in C

I would like to get some help with the following question.
I have a struct Node and I want to change it's insides using some method.
and I want to print the content of the changed struct inside my main method.
how do I get the struct changed and see the changed value in my main without returning the node as a return value.
I guess it might be solved with passing the struct Node as a pointer and then editing it.
what is the right way to do so?
for example:
typedef struct Node{
struct Node * right;
struct Node * left;
void * data;
}Node;
void insert(void * element, Node* root){
if(root==NULL){
root=(Node*)malloc(sizeof(Node));
root->data=element;
}
}
int main(){
Node a;
int b=8;
insert(&b,&a);
printf("%d",*(int*)a.data);
return 0;
}
printf doesn't print 8 it prints 1 (i guess some garbage)
It sounds like you are trying to do the following
Create a struct in one method, say main
Pass it to a second method, say example
Have example modify the struct and have the results visible in main
If so then the way to do this in C is by passing the struct as a pointer to example.
struct Node {
int data;
struct Node* pNext;
};
void example(struct Node* pNode) {
pNode->data = 42;
pNode->pNext = NULL;
}
int main() {
struct Node n;
example(&n);
printf("%d\n", n.data);
}
EDIT
Responding to the updated question.
To see the result of a modification of a Node you must pass a Node*. And accordingly to see the result of a Node* modification you need to pass a Node**. Essentially you need to pass one more level of indirection than the value you want to mutate / return.
void insert(void* element, Node** ppRoot){
if (NULL == *ppRoot) {
Node* pTemp = malloc(sizeof(Node));
pTemp->data = element;
*ppRoot = pTemp;
}
}

Resources