This question already has answers here:
How can I allocate memory and return it (via a pointer-parameter) to the calling function?
(11 answers)
Closed 7 years ago.
I am having problem while initializing the node value to passed pointer in C language,
I have written something like follow,
#include<stdio.h>
#include<stdlib.h>
struct node{
int data;
struct node *next;
};
void add(struct node *head, int val){
struct node *n1 = NULL;
n1 = (struct node *)malloc(sizeof(struct node ));
n1 -> data = val;
n1 -> next = NULL;
if(head == NULL){
head = n1;
printf("Head2 is initialized");
return;
}
}
int main(){
struct node *ptr = NULL;
struct node *temp;
add(ptr, 11);
printf("\nData = %d", ptr->data);
return 0;
}
Could you please tell me what is the issue in this code,
When i execute
printf("\nData = %d", ptr->data);
System shows Windows has stopped working
Thanks
short answer: if you want to change the value the pointer points to, you have to pass the pointer to the pointer:
void add(struct node **head, int val) {
...
if(*head == NULL){
*head = n1
}
int main(){
...
add(&ptr, 11)
...
}
long answer: when you call add(ptr, 11) in main you pass a memory address and a number. both memory address and a number are passed by value. as the result the changes to these variables are both local
in your add method - when you assign a value to head in head = n1 you change the value of your local variable to point to a new memory address. when your function returns the changes are gone, so main never sees the assignment and ptr remains NULL.
if you pass a pointer to ptr - &ptr, you will pass a location in memory where the value of ptr (which is memory address) resides in main, so when you call *head = n1* you write the address ofn1` the value in this location will change, and main will see it.
see also this question
Related
This question already has an answer here:
Dynamic memory access only works inside function
(1 answer)
Closed 8 months ago.
pointer to a struct
code that can not work
struct node
{
/* data */
int data;
};
void addnode(struct node* n)
{
n = (struct node*)malloc(sizeof(struct node));
printf("value of pointer n = %p",&n);
(*n).data = 9;
}
int main()
{
struct node * n1 = NULL;
addnode(n1);
printf("data is %d\n",n1->data);
}
but the code below is fine
struct node
{
/* data */
int data;
};
void addnode(struct node ** n1)
{
// the address of struct
*n1 = (struct node*)malloc(sizeof(struct node));
printf("address of pointer &n1 = %p\n",&n1);
printf("address of pointer *n1 = %p\n",*n1);
(*n1)->data = 99;
}
int main()
{
struct node * n1 = NULL;
//pass the address of pointer instead of value of it
addnode(&n1);
printf("address of pointer &n1 = %p\n",&n1); // self address
printf("address of pointer *n1 = %p\n",&(*n1)); // the address of struct
printf("data is %d\n",n1->data);
}
what makes me confused is why the indirect pointer as a parameter is working, instead of the direct pointer.
The 'indirect' pointer, as you called it, is actually 'a pointer to your pointer variable'.
If you inspect the value of n1 in your debugger, you will see, in your first example, that it will remain NULL (because you did not assign a new value to it).
In the second example however, you assign a value to the variable by accessing it's address.
Your first code can work too if it looks like this:
struct node
{
/* data */
int data;
};
struct node* addnode()
{
struct node* n = (struct node*)malloc(sizeof(struct node));
printf("value of pointer n = %p",&n);
n->data = 9;
return n;
}
int main()
{
struct node * n1 = NULL;
n1 = addnode();
printf("data is %d\n",n1->data);
}
This question already has answers here:
Changing address contained by pointer using function
(5 answers)
Closed 1 year ago.
I am trying to add a node to a binary search tree (BST). My adding method code is as follows:
int add(node_t* n, node_t* tn){
if(tn == NULL){tn = n;}
if(n->value < tn->value){add(n, tn->leftNode);}
else if (n->value > tn->value){add(n, tn->rightNode);}
else{return 0;}
return 1;
}
The method is called in main for BST t1 and node n1: add(n1, t1->root). The return value of the function is a 0 or 1, 0 if another node of the same value exists in the tree- in which case the new node is not added- and 1 if the node is successfully added. Struct tree_t's count variable is updated in the main function as follows: t1->count += add(n1, t1->root).
However, after I call the add function, the tree t1 still seems to be empty. My only guess is that add is adding a node to a copy of t1 which is being destroyed after the function call, but I don't understand why this is the case as it is passed in as a pointer.
The structs tree_t and node_t are attached below:
typedef struct node{
int value;
struct node* leftNode;
struct node* rightNode;
} node_t;
typedef struct tree{
struct node* root;
int count;
} tree_t;
And here is my main method:
int main(){
tree_t t1;
tree_init(&t1);
node_t n1;
node_init(&n1, 5);
node_t n2;
node_init(&n2, 7);
t1.count += add(&n1, t1.root);
t1.count += add(&n2, t1.root);
print_tree(t1.root); //this prints nothing, and I'm confident that print_tree works
}
Any help is greatly appreciated!
If you pass to function pointer to type, you can change the variable that pointer points to. But you can't change the address, that this pointer points to (can't change pointer itself).
If you want to change pointer itself (address that he points to), you need to pass in your function pointer to pointer:
int add(node_t *n, node_t **tn){
if(*tn == NULL){*tn = n;}
if(n->value < *tn->value){add(n, *tn->leftNode);}
else if (n->value > *tn->value){add(n, *tn->rightNode);}
else{return 0;}
return 1;
}
Why cant I assign a pointer to a double pointer's pointer? I get segmentation fault every time.
#include <stdio.h>
int main() {
int **pointer1, *pointer2, *pointer3, var;
var = 10;
pointer3 = &var;
pointer1 = &pointer3;
pointer2 = *pointer1; //correcting my mistake, so this is now correct?
return 0;
}
The code I was actually working on, practicing linked list:
#include <stdio.h>
#include <stdlib.h>
typedef struct node_t {
int num;
struct node_t *next;
} node_t;
void insert(int, node_t**);
int main(void) {
int list;
node_t **head, *temp;
*head = NULL;
while (scanf("%d", &list) != EOF) {
insert(list, head);
}
temp = *head;
/*while (temp != NULL) { //here is the problem, if I remove this
//I get segmentation fault but it runs
printf("%d ", temp->num); //runs fine when I include it
temp = temp->next;
}*/
return 0;
}
void insert(int list, node_t **head) {
node_t *temp = malloc(sizeof(node_t));
temp->next = (*head);
temp->num = list;
(*head) = temp;
}
Just like what I put in the code comment, the above version of my code gets segmentation fault when I compile it without the while loop. But weirdly enough, it works fine once I include the while loop. After fiddling around, I suspect the culprit to be the double pointer in which I tried to assign the secondary address into a regular pointer.
But this version actually runs fine:
#include <stdio.h>
#include <stdlib.h>
typedef struct node_t {
int num;
struct node_t *next;
} node_t;
void insert(int, node_t**);
int main(void) {
int list;
node_t *head, *temp;
head = NULL;
while (scanf("%d", &list) != EOF) {
insert(list, &head);
}
temp = head;
while (temp != NULL) {
printf("%d ", temp->num);
temp = temp->next;
}
return 0;
}
void insert(int list, node_t **head) {
node_t *temp = malloc(sizeof(node_t));
temp->next = (*head);
temp->num = list;
(*head) = temp;
}
Over here I passed the address into the linked list function and essentially I'm doing the same thing but without the double pointer.
On a side note, I have seen many different implementations of linked lists. Mine requires the double pointer because I'm using a void insert(int, **node_t), but there are versions which returns the address and updates the head: node_t* insert(int, *node_t) and Global linked list: void insert(int). Just wondering which versions are actually recommended, easier to debug and beginner friendly.
Your first example segfaults because *pointer1 (and pointer1 before it) isn't pointing to anything. It's an uninitialized pointer that points to random garbage data in memory.
Trying to dereference such a pointer (**pointer1 = 10;) results in a segfault.
A solution to make your first example work would be to allocate some memory for the data you're trying to store :
int **pointer1, *pointer2;
int *data = malloc(sizeof(int));
pointer1 = &data;
**pointer1 = 10;
pointer2 = *pointer1;
free(*pointer1); //or free(data)
When you do this:
**pointer1 = 10;
What this says is "take the address stored in pointer1, dereference that address, take the address stored there, dereference again, and store the value 10 at that location".
It looks something like this:
pointer1
------- ------- ------
| .--|---->| .--|--->| 10 |
------- ------- ------
You're getting a segfault because pointer1 doesn't currently point anywhere.
This could work if you do something like this:
int **pointer1, *pointer2, value;
value = 10;
pointer2 = &value;
pointer1 = &pointer2;
In the case of the two "real" code snippets, the problem with the first piece of code is that you pass head uninitialized to insert, which then subsequently dereferences head. This is the same problem as above. The same thing happens again in main because head is still uninitialized after calling list because it was passed by value. The second piece of code works because you pass the address of head to insert, so subsequently dereferenced it is valid.
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);
I'm implementing a simple priority queue in C for a kernel and so I can't use any standard libraries. The queue holds a head node and each node points to the next in the queue.
typedef struct node node;
struct node {
node *next;
void *data;
};
typedef struct {
node *head;
int n;
} queue;
As you can see, each node holds it data in a void*. I'm having trouble converting this data to lets say an int when I pop the data off the stack.
//push data
int int_data = 100;
push(q, &int_data);
//...
//pop data
node* popped = pop(q);
int *pop_data = popped->data;
printf("pop data (100): %d\n", *pop_data);
Why can't I get the original value here? I seem to be printing a pointer value. Alternatively, is there a better way to handle this?
== edit (sorry should have included these):
void push(queue *q, void *data)
{
node new;
new.data = data;
node *new_ptr = &new;
if(is_empty(q))
{
q->head = new_ptr;
q->n++;
return;
}
int i;
node *curr = q->head;
for(i=0; i<q->n; i++)
{
curr = curr->next;
}
curr->next = new_ptr;
q->n++;
}
node* pop(queue *q)
{
node *curr = q->head;
q->head = curr->next;
return curr;
}
Is your code all in one function? If not, int int_data is getting popped off the stack (not your queue, the actual stack) which is probably why you are printing garbage; you are storing the address of a local variable.
I would suggest changing void* data to int data. (If you need to, you can store an address in an int and can cast it back to a pointer later.)
int int_data = 100;
push(q, int_data);
node* n = pop(q);
int num = n->data;
After reviewing your code again, you have the same problem when adding a new node. node new falls out of scope at the end of the function, so basically all of your nodes in your queue are pointing to invalid memory.
If the "pop" operation is in a different function:
The problem is likely because you're pushing a local variable into your queue.
When you go to pop, this address is no longer valid (or at least not pointing to an int value), so you're printing something strange. As the data is no longer pointing to your int, it probably looks like a memory address.
You can use the glib GPOINTER_TO_INT macro:
#define GPOINTER_TO_INT(p) ((gint) (glong) (p))
But please, take note with the doc note:
YOU MAY NOT STORE POINTERS IN
INTEGERS. THIS IS NOT PORTABLE IN ANY
WAY SHAPE OR FORM. These macros ONLY
allow storing integers in pointers,
and only preserve 32 bits of the
integer; values outside the range of a
32-bit integer will be mangled.
are you setting data = int_data (i.e. int --> void*) or data = &int_data (i.e. int* --> void *) ? In the former case, you have to write printf("pop data (100): %d\n", pop_data);