I am creating a simple binary search tree.When I am calling the add method using head pointer,changes made in the method are not reflected to this head pointer.It still points null.
struct node *add(struct node *root,int data)
{
if (root==NULL)
{
root=(struct node *) malloc(sizeof(struct node));
root->data=data;
root->left=NULL;
root->right=NULL;
return root;
}
else
{
if (data<=root->data)
{
root->left=add(root->left,data);
}
else
{
root->right=add(root->right,data);
}
return root;
}
}
I am calling the function as
struct node *head=NULL;
add(head,1);
add(head,3);
add(head,15);
In my understanding, on calling the add method, root=head, so head would point to the same memory location where root is pointing and should be updated with the changing value of root accordingly.
UPDATE
head=add(head,1);
When you pass a pointer (node* here), you just copy the value of the memory address it's pointing to, you can change the contents of this address in the function, but the pointer outside of it would still contain the same address.
Initially you have head = NULL, it's not pointing anywhere. When you call the function you create a local variable called root, and copy the value of the pointer (NULL) into that. You then allocate some space and change root to point there, but changes to the local variable would be lost once you leave the function, and head outside will continue holding the value NULL. You actually lost the memory you allocated as no one points there any longer (valgrind could have told you that).
If you passed &head to the function instead (the type would then be node**, note that you'd have to use *root inside the function this way), the changes would be made directly on the outside variable (thanks to the fact c would actually pass the address where main() allocated it on the stack directly to the function).
By the way, in c++, Passing the value by reference would emulate the same thing internally and would be even simpler (you'll be able to keep your code referring to root as is).
Alternatively, you can just return the value of the new head pointer from the function. This would limit you to a single return value though (which is fine in this case)
Related
I want the value of a pointer variable to be initialized to NULL at the start of the execution. This variable is used in a function and its value may also get changed within the function. But I do not want the value of this variable to reset to NULL whenever a function call is made. Instead, its value should be equal to the updated value from its previous function call. Cannot use global variables.
void function(struct node *variable) {
// changes value of pointer variable to something else
variable = something;
}
void another_function(void) {
// have to be initialised before passing in as argument or else will raise error
struct node *variable = NULL;
function(variable);
}
// then calling this function multiple times in main
another_function();
another_function();
help would be much appreciated.
Firstly, the pointer variable variable is local to another_function. It does not live outside of this scope.
Secondly, when you pass it to function, the variable parameter of that function is also local to that function. You immediately assign a value to that local variable, but that doesn't change the variable you passed in.
You can use the static keyword when declaring your initial pointer variable.
It will only be initialized when first encountered during the execution.
But as for now, your code will probably not do what you intend it to do.
The pointer variable in function is local and will have no effect on the value of variable in another_function.
You should use a pointer of pointer (also called a double-pointer or a nested pointer) for this effect.
Here is an example of how to use a double-pointer :
struct node {
int value;
};
void function(struct node** variable) {
if(*variable == NULL) {
*variable = (struct node*)malloc(sizeof(struct node));
(*variable)->value = 1;
}
printf("Value of variable is %d\n", (*variable)->value);
// Creating another struct node just for the demonstration
struct node* newnode = (struct node*)malloc(sizeof(struct node));
newnode->value = (*variable)->value + 1;
*variable = newnode;
}
void another_function() {
static struct node* variable = NULL;
function(&variable);
}
Basically, you pass the address of a pointer (located on the stack, which will always have a memory address) which let you modify the content of this pointer (a memory address on the heap) in the receiving function.
When you are dereferencing variable in function, what you get is not a value but another pointer.
Also parenthesis are important in this case.
Nested pointers can really be confusing, I hope that my explanation is somewhat clear.
To really understand how it works you need to understand what it's on the stack and what it's on the heap. But maybe this is an explanation for another time.
Of course, there is no memory management in this example and what I wrote contains memory leaks from all struct node that never are deallocated.
You should figure out how to do it depending on your program architecture.
I have the following function to append a double value at the end of a linked list.
void deappendlinked(dNODE *head,double value){
while(head!=NULL){
if(head->next==NULL){
break;
}
head=head->next;
}
dNODE *newElement=memalloc(sizeof(dNODE));
newElement->data=value;
newElement->next=NULL;
head->next=newElement;
}
It receives the head, i.e., the address of the first element of the linked list, which I iterate through to the end.
As I'm not passing a pointer of a pointer, I do not need a temporary variable to hold the value of the head, correct? (I.e. I can just do what I did – at least it works.)
As I'm not passing a pointer of a pointer, I do not need a temporary variable to hold the value of the head, correct?
That is correct. The function will receive a copy of the pointer passed by the calling module. In that module, the value of that pointer will not be changed by your function (i.e. it will remain pointing at the head of the list).
As an aside, even if you know that your passed head value will not (read: should not) be NULL, it is still better to add a check for that, in case a future editor of your code does something silly.
Also, your while loop can be much simplified:
void deappendlinked(dNODE *head,double value) {
if (head == NULL) {
// Optional error message?
return;
}
while (head->next != NULL) head = head->next;
dNODE *newElement=memalloc(sizeof(dNODE));
newElement->data=value;
newElement->next=NULL;
head->next=newElement;
}
I have a structure like this
struct node
{
int data;
struct node* next;
};
Which I use to create singly linked list.
I created other functions like
int push(struct node* head,int element);
which pushes data onto stack created using node structs.
The function then tries to update the struct node* head passed to it using code(it does other things as well)
head=(struct node*)malloc(sizeof(struct node));
The call is made as such
struct node* stack;
push(stack,number);
It looks like this code created copy of the pointer passed to it. So I had to change the function to
int push(struct node** head,int element)
and
*head=(struct node*)malloc(sizeof(struct node));
The call is made as such
struct node* stack;
push(&stack,number);
So my question is, what was the earlier function doing? Is it necessary to pass struct node** to the function if I want to update original value of pointer or is my approach wrong?
Sorry I cannot provide complete code as it is an assignment.
C always passes by value. To change a variable passed to a function, instead of passing the variable itself, you pass a reference(its address).
Let's say you're calling your function with the old signature
int push(struct node* head,int element);
struct node *actual_head = NULL;
push(actual_head, 3);
Now before calling push, your variable actual_head will have value as NULL.
Inside the push function, a new variable head will be pushed to stack. It will have the same value as passed to it, i.e. NULL.
Then when you call head = malloc(...), your variable head will get a new value instead of actual_head which you wanted to.
To mitigate the above, you'll have to change the signature of your function to
int push(struct node** head,int element);
struct node *actual_head = NULL
push(&actual_head, 3);
Now if you notice carefully, the value of actual_head is NULL, but this pointer is also stored somewhere, that somewhere is its address &actual_head. Let's take this address as 1234.
Now inside the push function, your variable head which can hold the address of a pointer(Notice the two *), will have the value of 1234
Now when you do *head = malloc(...), you're actually changing the value of the object present at location 1234, which is your actual_head object.
C always passes parameters by value (i.e., by copying it). This applies even to pointers, but in that case, it is the pointer itself that is copied. Most of the times you use pointers, that is fine, because you are interested in manipulating the data that is pointed to by the pointer. However, in your situation, you want to modify the pointer itself, so you do indeed have to use a pointer to a pointer.
Yes.
The first version of your program was passing the pointer by value. Although it passed an address (held by the pointer to struct) it didn't pass the pointer's address - necessary to update the value.
Whenever you want to update a variable's value you must pass the variable's address. To pass a pointer address, you need a parameter pointer to pointer to type.
In your case, pointer to pointer to struct node.
The code is not doing what you think but not because it creates a copy of the node, it creates a copy of the pointer.
Try printing
fprintf(stdout, "Address of head: %p\n", (void *) head);
both, inside push() and in the caller function.
The pointer you pass in and the parameter have different addresses in memory although they both point to the same address, storing the result of malloc() in it doesn't persist after the funcion has returned.
You need to pass a pointer to the pointer like this
int push(struct node **head, int element)
{
/* Ideally, check if `head' is `NULL' and find the tail otherwise */
*head = malloc(sizeof(**head));
if (*node == NULL)
return SOME_ERROR_VALUE;
/* Do the rest here */
return SOME_SUCCESS_VALUE_LIKE_0;
}
And to call it, just
struct node *head;
head = NULL;
push(&head, value);
/* ^ take the address of head and pass a pointer with it */
of course, the push() implementation should be very differente but I think you will get the idea.
Everything everybody has said is absolutely correct in terms of your question. However, I think you should also consider the design. Part of your problem is that you are conflating the stack itself with the internal structures needed to store data on it. You should have a stack object and a node object. i.e.
struct Node
{
int data;
struct Node* next;
}
struct Stack
{
struct Node* head;
}
Your push function can then take a pointer to the Stack without any double indirection. Plus there is no danger of pushing something on to a node that is in the middle of the stack.
void push(struct Stack* stack, int value)
{
struct Node* node = malloc(sizeof node);
node->data = value;
node->next = stack->head;
stack->head = node;
}
The function
int push(struct node* head,int element) {
head=(struct node*)malloc(sizeof(struct node));
}
allocate some memory and throw it away (cause memory leak).
Passing “pointer to structure” to a function do create local copies of it.
It is necessary to pass struct node** to the function if you want to update original value of pointer. (using global variables is generally considered as a bad idea)
When you pass stack to your function push(struct node* head,int element)
and do
head=(struct node*)malloc(sizeof(struct node));
The pointer head will update to the memory allocated by malloc() and stack is unaware of this memory as you just passed the value.(which is uninitialized here)
When you pass the address then you have a pointer to pointer which makes the changes inside push() to be reflected on stack
So my question is, what was the earlier function doing?
Your earlier function was defined to receive a pointer to an object. You passed your function an uninitialized struct node pointer. A function can't do anything with a value representing an uninitialized pointer. So your function was passed garbage, but no harm was done because your function immediately ignored it by overwriting with a pointer to allocated memory. Your function is not using the value you passed for anything except temporary local storage now. Upon return from your function, your parameters to the function are thrown away (they are just copies), and the value of your stack variable is as it was before, still uninitialized. The compiler usually warns you about using a variable before it is initialized.
By the way, the pointer value to the allocated memory was also thrown away/lost upon function return. So there would now be a location in memory with no reference and therefore no way to free it up, i.e., you have a memory leak.
Is it necessary to pass struct node** to the function if I want to update original value of pointer or is my approach wrong?
Yes, it is necessary to pass the address of a variable that you want filled in by the function being called. It must be written to accept a pointer to the type of data it will supply. Since you are referencing your object with a pointer, and since your function is generating a pointer to your object, you must pass a pointer to a pointer to your object.
Alternatively, you can return a pointer as a value from a function, for example
struct node * Function() { return (struct node *)malloc(sizeof(struct node)); }
The call would be...
struct node *stack;
stack = Function();
if(stack == NULL) { /* handle failure */ }
So, your approach is not wrong, just your implementation (and understanding) need work.
I've been trying to learn C by myself after basic Java knowledge and I'm trying to implement a linked list. I'm running into trouble when making a createList function - a function that's supposed to make an empty list. I'm having a bit of a weird problem with passing pointers though. These are just snippets of the code, and my definitions of the node / list are located in a header file given by a book CD (so that's not the problem)
LList* createList(void){
LList list;
list.first = NULL;
printf("List from mk_list: \nfirst:%d\nlist address:%d\n",list.first,&list);
return &list;
} //This prints 0 and then the address of list
void print_list(LList *list){
printf("\nList from print_List\nFirst%d\nAddress:%d\n", list->first,list);
} //This prints some random non-null address for some reason, but also the
//SAME address as the list from createList. Why does list->first not print as 0?
int main(void)
{
LList*newList = createList();
printf("\nList from main:\nFirst:%d\nAddress:%d\n", newList->first,newList);
print_list(newList);
system("pause");
return 0;
} //Prints same exact thing as the printf in the createList.
return &list;
list resides on stack and its lifetime completes as function returns. So, using a pointer to it invokes undefined behavior.
Create the object on heap.
Here is your problem:
LList* createList(void)
{
LList list;
...
return &list;
}
Variable list is allocated on the stack, whenever you enter the code of function createList.
Whenever this function (or any other function for that matter) is called, the stack is in a different status.
Sometimes it's 75% full, sometimes only 24% (this is just a figure of speech though).
Your local variable is allocated at the next free slot in the stack, so it doesn't have a constant address throughout the lifetime of your program, but only during the execution of the function itself.
Shorty after the function returns, some other local variable might be allocated in the same address.
Hence, there is no point in returning this address, as you are doing in your code.
UPDATE:
One optional solution for you is to declare LList newList in main, and pass &newList to createList instead of returning a value from that function:
void createList(LList* list)
{
list->first = NULL;
printf("List from mk_list: \nfirst:%d\nlist address:0x%X\n",list->first,list);
}
P.S.: You should probably name this function initList instead.
I have found this piece of code in a book:
void DeleteList(element *head)
{
element *next, *deleteMe;
deleteMe = head;
while (deleteMe) {
next = deleteMe->next;
free(deleteMe);
deleteMe = next;
}
}
Assuming that the argument that we are passing to the function is the pointer to the head of the list, why are we not passing a reference to that pointer?
If we don't do that, aren't we just going to delete a local copy of that pointer? That is why we pass reference pointers right? So the callee get the changes that have been done inside the function?
If we don't do that, aren't we just going to delete a local copy of that pointer?
Well, there is no such thing as a reference in C, but I assume you mean a pointer-to-pointer, and the answer would be no.
You are freeing the memory that the pointer points to on the heap, not the pointer itself. You are not mutating the pointer, so a copy is fine. Regardless of whether it is a copy or not, they point to the same place.
You are confusing this with assigning a completely new value to a variable passed to a function, in which case you would need to take a pointer-to-pointer. for example:
// only changes the local copy
void init(some_type *foo) {
foo = malloc(sizeof(some_type));
}
// initializes the value at *foo for the caller to see
void init(some_type **foo) {
*foo = malloc(sizeof(some_type));
}
Passing a pointer to a pointer (not a reference to a pointer, because C does not have references at all) would be a better solution, because you'd be able to null it out after the deletion. As it is currently defined, the function may leave dangling pointers behind if its caller is not careful. Other than that little problem, this solution is valid: the caller can always assign NULL to the list head manually after passing it to DeleteList().
Here is how I would rewrite this with a pointer to pointer:
void DeleteList(element **head) {
element *next, *deleteMe;
deleteMe = *head;
while (deleteMe) {
next = deleteMe->next;
free(deleteMe);
deleteMe = next;
}
*head = NULL;
}
The code from #dasblinkenlight can be made more compact.
void DeleteList(element **head) {
element *deleteMe;
while ((deleteMe = *head)) {
*head = deleteMe->next;
free(deleteMe);
}
}
When calling free, the pointer itself is not changed, so there is no need to pass it by reference.
You don't need to change the value of the head of the list in the caller.
// caller
DeleteList(head);
// head points to an invalid place (the place where the list used to be)
// for convenience sake, reset to NULL
head = NULL;