So I'm trying to add an element to the beginning of a list. The function prepend_list is at line 27. I'm trying to make it in two different ways, one returns a list back and one is a void function.
#include "base.h"
#include "string.h"
typedef struct Node Node;
struct Node{
int value;
Node* next;
};
Node* new_node(int value, Node* next){
Node* new = xmalloc(sizeof(Node));
new->value = value;
new->next = next;
return new;
}
void free_list(Node* list){
Node* currentHead = list;
while(list != NULL){
currentHead = list;
list = list->next;
free(currentHead);
}
}
Node* prepend_list(int value, Node* list){
return new_node(value, list);
}
void test(void) {
Node* n = NULL;
n = new_node(1, new_node(3, NULL));
n = prepend_list(2, n);
for(Node* print = n;print != NULL;print = print->next){
printi(print->value);
if(print->next != NULL){
prints(", ");
}
}
printsln("");
free_list(n);
}
int main(void) {
test();
report_memory_leaks(true);
return 0;
}
But I don't understand why I can't do this instead
void prepend_list(int value, Node* list){
list = new_node(value, list);
}
When I tried this, the list n in the test function didn't change at all. Instead I got memory leaks. Can somebody tell me why?
The function deals with a copy of the value of the expression passed to the function as an argument.
You can imagine the function
void prepend_list(int value, Node* list){
list = new_node(value, list);
}
and its call
Node* n = NULL;
prepend_list(2, n);
the following way
prepend_list(2, n);
//...
void prepend_list(/* int value, Node* list */){
int value = 2;
Node* list = n;
list = new_node(value, list);
}
As you can see the local variable list of the function is initialized by the value of the passed pointer n and within the function it is the local variable list that is changed. The pointer n stays unchanged. That is the function accepts its argument by value.
There are two approaches to resolve the problem and to change the original pointer.
The first one is return from the function a new pointer and assign it to the original pointer as it is done in your program.
n = prepend_list(2, n);
The second one is to pass the original pointer by reference indirectly through a pointer to it. And dereferencing the pointer to the original pointer the function can have an access to the original pointer and can change it. For example
prepend_list(2, &n);
//...
void prepend_list(int value, Node ** list){
*list = new_node(value, *list);
}