allocation of local variable inside a method/function - c

I was making a dynamic linked list in C, something similar to what we have in Java.
I was wrapping the element/value inside a struct which has the value and the address of the next node. I didn't feel like passing an instance of the struct itself, so I made a method that accepts the value and adds that value in the struct((you can say this struct is abstracted out, someone using the method won't know that there a struct being used inside the method) and then adds that struct to the list.
To test the code, I added 5 different integers and that struct I made inside the method got the same memory address during all the 5 additions.
This code was compiled using gcc and was written and tested in ubuntu.
struct node {
void* value; // literal values can't be passed in here, only address can be passed
struct node* next; // poninter to the next node
};
typedef struct {
size_t size; // size of the linked list
struct node* head; // head node of the list, always points to the first element in the list
} link_list;
void link_list_add(link_list * list, struct node * ele) {
// if size is zero, simply add the node to the list
if(list->size==0) {
list->head = ele;
ele->next = NULL;
}
else {
// add the new node to the front of the list and make in point towards what is being pointed by the list head
ele->next = list->head;
list->head = ele;
}
list->size++;
}
// does the same thing as the previous method, the only difference being that it takes the address of the element that needs to add and makes the wrapper node struct for it.
void link_list_add_ele(link_list * list, void * ele){
struct node eleNode = {ele, NULL}; // this gives the same address every single time.
link_list_add(list, eleNode);
}

This defines a local variable:
struct node eleNode = {ele, NULL}; // this gives the same address every single time.
It is allocated when the link_list_add_ele function is called and freed when the function returns. The next time you call the function, its memory might be reused.
What you're looking for is a dynamic memory allocation (like new in Java):
void link_list_add_ele(link_list * list, void * ele){
struct node *eleNode = malloc(sizeof(struct node));
eleNode->value = ele;
eleNode->next = 0;
link_list_add(list, eleNode);
}
But remember that such memory would also need to be explicitly freed by a call to free(), as C doesn't have a garbage collector.

Stack memory like struct node eleNode = {ele, NULL}; is no longer valid once the function returns. After the function returns the memory will be reused.
Anything simpler than basic type like a float, integer, or pointer that you want to return you need to use malloc to allocate heap memory. That memory will remain allocated until it is freed or the program exits.
It's a good idea to put your struct allocation and freeing into a function for DRY purposes and to isolate it from the rest of the code. While it's simple now, struct allocation is often complicated.
struct node *node_new {
return malloc(sizeof(struct node));
}
void link_list_add_ele(link_list * list, void * ele){
struct node *eleNode = node_new();
eleNode->value = ele;
eleNode->next = NULL;
link_list_add(list, eleNode);
}
And when you delete a node you must free the memory.
void node_free(struct node *node) {
free(node);
}

What you have been observing is right. The Linked List nodes should be allocated dynamically (i.e, using functions like malloc, calloc or realloc) if you want to use the Linked List beyond the scope of the function in which you have created it. You need to free the dynamically allocated memory once they are not needed. If you don't do that, then you will have memory leaks.
To test the code, I added 5 different integers and that struct I made inside the method got the same memory address during all the 5 additions.
It is because you have been allocating the node over Stack memory and hence, it has automatic storage class (Learn more about Storage Classes). The memory location allocated to that node will destroyed when you exit from your function link_list_add_ele. It is no longer valid once the wrapper function returns.
One more point:
You have been passing wrong parameters to link_list_add. The second parameter is a pointer but you have been passing it a value.
One important remark:
Try to understand various Warnings and Errors thrown by your compiler.
In my Linux, I try to compile my code with various verbose warning flags.
gcc example.c -o example -Wall -Wextra -Wshadow
If you are using an IDE, then there will be some settings options to enable warning.
I compiled your code with gcc filename.c -Wall and it gave me this error:
error: incompatible type for argument 2 of ‘link_list_add’
link_list_add(list, eleNode);
^~~~~~~
note: expected ‘struct node *’ but argument is of type ‘struct node’
void link_list_add(link_list * list, struct node * ele) {
I have edited your function to remove the Warnings and allocated the memory over heap:
#include <stdio.h>
#include <stdlib.h>
void link_list_add_ele(link_list *list, void *ele)
{
struct node *eleNode = malloc(sizeof(struct node)); // this gives the same address every single time.
eleNode->value = ele;
eleNode->next = NULL;
link_list_add(list, eleNode);
}
You also need to include the header file #include <stdlib.h> and don't forget to free the memory once it is not needed as C doesn't have automatic garbage collection and hence, you may observe memory leaks if you don't free them properly.

Related

Why use dynamic memory allocation(i.e. malloc()) when implementing linked list in c?

Okay this question may sound stupid to the amateur programmers . But seriously this is bothering me and a solemn answer to this doubt of mine is welcomed. I have just started to take my first ever course in data structures. And what is bothering me is this:
Assuming C is used,
//Implementing a node
struct Node
{
int data;
struct *Node;
};
Now while creating a node why do we use the dynamic memory allocation technique where we use malloc(). Can't we just create a variable of type ' Struct Node '.
i.e. something like:
struct Node N1;
//First node - actually second where !st Node is assumed to be Head.
struct Node *Head = &N1;
struct Node N2;
N2.(*Node) = &N1;
Well some parts of my code may be incorrect because I am only a beginner and not well versed with C. But by know you may have understood what I basically mean. Why don't we create variables of type Node of an Array of type Node to allocate memory t new nodes why get into the complexity of dynamic memory allocation?
First off, you have an error in how you declare your struct. struct * by itself does not denote a type. You have to give the full type name:
struct Node
{
int data;
struct Node *Node;
};
You can certainly use local variables as above to make a linked list, however that limits you to a fixed number of list elements, i.e. the ones you explicitly declare. That would also mean you can't create a list in a function because those variables would go out of scope.
For example, if you did this:
struct Node *getList()
{
struct Node head, node1, node2, node3;
head.Node = &node1;
node1.Node = &node2;
node2.Node = &node3;
node3.Node = NULL;
return &head;
}
Your list would be restricted to 4 elements. What of you needed thousands of them? Also, by returning the address of local variables, they go out of scope when the function returns and thus accessing them results in undefined behavior.
By dynamically allocating each node, you're only limited by your available memory.
Here's an example using dynamic memory allocation:
struct Node *getList()
{
struct Node *head, *current;
head = NULL;
current = NULL;
// open file
while (/* file has data */) {
int data = /* read data from file */
if (head == NULL) { // list is empty, so create head node
head = malloc(sizeof(struct Node *));
current = head;
} else { // create new element at end of list
current->next = malloc(sizeof(struct Node *));
current = current->next;
}
current->data = data;
current->Node = NULL;
}
// close file
return head;
}
This is psedo-code that doesn't go into the details of reading the relevant data, but you can see how you can create a list of arbitrary size that exists for the lifetime of the program.
If these variables are local, defined inside a function's scope (i.e. stored on the stack), you shouldn't do this, because accessing them after leaving their scope will result in undefined behavior (their contents will likely be overwritten as you call other functions). In fact, any time you return a pointer to a local, stack based variable from your function, you are doing the wrong thing. Given the nature of C, this is problematic since nothing will warn you you are doing something wrong, and it will only fail later when you try to access this area again.
On the other hand, if they are declared as global variables (outside any other function), then you are simply limited by the number of variables declared that way.
You can potentially declare many variables, but keeping track of which one is "free" for use will be painful. Sure, you can even go a step further and say you will have a global preallocated array of nodes to prevent using malloc, but as you are doing all this you are only getting closer to writing your own version of malloc, instead of sticking to the existing, dynamic one.
Additionally, all preallocated space is wasted if you don't use it, and you have no way of dynamically growing your list in runtime (hence the name dynamic allocation).
Here is some good reasons to use dynamic memory
When you declare node struct Node N1;this node will store on stack memory. After scope of the node that will get destroy auto.But in case of dynamic you have handle to free the memory when you done.
When you have some memory limitation.
When you don't know the size of array then dynamic memory allocation will help you.
One issue could be that you cannot use another function to add a new node to your list.
Remember that automatic variables - like the ones created by struct Node node100; - have scope only inside the function in which they are defined. So when you do something like this:
int main()
{
struct Node *head;
/* Some code there you build list as:
head ---> node1 ---> node2 --> .. ---> node99
*/
/* Add a new node using add_node function */
add_node(head, 555);
/* Access the last node*/
}
void add_node(struct Node *head, int val)
{
/* Create new node WITHOUT using malloc */
struct Node new_node;
new_node.data = val;
/* add this node to end of the list */
/* code to add this node to the end of list */
/* last_element_of_list.next = &new_node*/
return;
}
Now you think that you have added a new node to the end of the list. But, unfortunately, its lifetime ends as soon as the add_node function returns. And when you try to access that last node in your main function your program crashes.
So, to avoid this situation you will have put all your code in one single function - so that the lifetime of those nodes do not end.
Having all your code in ONE function is bad practice and will lead to many difficulties.
This was one situation that asks for a dynamic memory allocation, because, a node allocated with malloc will be in scope untill it is freed using free, and you can put code that do different things in different functions, which is a good practice.
You don't have to use dynamic memory to create a linked list, although you definitely don't want to create separate variables for each node. If you want to store up to N items, then you'd need to declare N distinct variables, which becomes a real pain as N gets large. The whole idea behind using a linked list is that it can grow or shrink as necessary; it's a dynamic data structure, so even if you don't use malloc and free, you're going to wind up doing something very similar.
For example, you can create an array of nodes at file scope like so:
struct node {
int data;
struct node *next;
};
/**
* use the static keyword to keep the names from being visible
* to other translation units
*/
static struct node store[N]; /* our "heap" */
static struct node *avail; /* will point to first available node in store */
You the initialize the array so each element points to the next, with the last element pointing to NULL:
void initAvail( void )
{
for ( size_t i = 0; i < N - 1; i++ )
store[i].next = &store[i + 1];
store[N - 1].next = NULL;
avail = store;
}
To allocate a node for your list, we grab the node avail points to and update avail to point to the next available node (if avail is NULL, then there are no more available nodes).
struct node *getNewNode( void )
{
struct node *newNode = NULL;
if ( avail ) /* if the available list isn't empty */
{
newNode = avail; /* grab first available node */
avail = avail->next; /* set avail to point to next available node */
newNode->next = NULL; /* sever newNode from available list, */
} /* which we do *after* we update avail */
/* work it out on paper to understand why */
return newNode;
}
When you're done with a node, add it back to the head of the available list:
void freeNode( struct node *n )
{
n->next = avail;
avail = n;
}
We're not using dynamic memory in the sense that we aren't calling mallic or free; however, we've pretty much recapitulated dynamic memory functionality, with the additional limitation that our "heap" has a fixed upper size.
Note that some embedded systems don't have a heap as such, so you'd have to do something like this to implement a list on such systems.
You can write a singly linked list with out malloc , but make sure the implementation is done in main. but what about writing program for traversing , finding least number ,etc . these struct node variables will go out of scope .
struct node{
int a;
struct node* nextNode;
};
int main()
{
struct node head,node1,node2;
head.a=45;
node1.a=98;
node2.a=3;
head.nextNode=&node1;
node1.nextNode=&node2;
node2.nextNode=NULL;
if(head.nextNode== NULL)
{
printf("List is empty");
}
struct node* ptr=&head;
while(ptr!=NULL)
{
printf("%d ",ptr->a);
ptr=ptr->nextNode;
}
}

C linked list can't properly add data to list

Bit of a lengthy question so please bear with me. I am trying to create a doubly linked list in C using a dummy node as the head. For whatever reason, however, the list only saves the last node I read into it, and links the prev node pointer and the next node pointer to that last node, so if I try and iterate over the list, it gets stuck in an infinite loop.
Here is my node header file and C file. The linked list implementation isn't meant to be a full linked list implementation, so I only included the functions I need:
node.h:
#ifndef _node_h
#define _node_h
#include "task_block.h"
#include <stdio.h>
typedef struct node {
task_block_type *data;
struct node *next;
struct node *prev;
}node_t;
node_t *node_new(task_block_type *data);
void add(node_t *new, node_t *head);
#endif
node.c:
#include "node.h"
#include "task_block.h"
#include <stdlib.h>
node_t *node_new(task_block_type *data) {
node_t *node = NULL;
node = malloc(sizeof(node_t));
node->data = data;
node->next = NULL;
node->prev = NULL;
return node;
}
void add(node_t *new, node_t *head) {
node_t *current = head;
if (head->next == NULL) {
head->next = new;
head->next->prev = head;
return;
}
while(current->next != NULL) {
current = current->next;
}
current->next = new;
current->next->prev = current;
return;
}
And finally, the code that is messing up from main.c:
while (j < numTasks) {
if (tasks[j].taskID == currentID) {
*newTask = *task_block_new(tasks[j].taskID, tasks[j].period);
newTask->startTime = starts[i];
newTask->deadline = deadlines[i];
newTask->executionTime = executions[i];
*nodeNew = *node_new(newTask);
add(nodeNew, eventQueue);
}
I have already tested that my new task_block_type get the correct data form the text file and that the new node I create is initialized properly with the task block. Once I read it into my list with add(), however, it messes up. Any help would be greatly appreciated as I've been trying to fix this problem for several hours now and still haven't found a solution
EDIT:
self contained example:
*node_new is meant to be a constructer for my node objects and is supposed to return a pointer to a node object. So for example, say instead of having a node which contains the task_block_type as above, I have one that contains an int. If I wanted to initialize it with a value of 5, I would call
*newNode = (node_t *)malloc(sizeof(node_t));
*newNode = *node_new(5);
Hope that helps
Change this:
*nodeNew = *node_new(newTask);
To this:
nodeNew = node_new(newTask);
Your original code copies the (dereferenced) value returned by node_new() to the value at (dereference of) *nodeNew. Thus, the pointer nodeNew never gets updated with the address of the new node created by node_new()... so you keep overwriting the value at *nodeNew while passing its unchanging address to add().
And you get a memory leak into the bargain. You are responsible for free()ing every pointer ever returned to you by malloc(). But here, for the same reason given above, you're not keeping copies of the returned pointers to enable this... just linking to nodeNew over and over again.
You need to update the pointer nodeNew with the location of, well, each new node, before passing it on to add(). Then you'll actually be linking different nodes, and at their original addresses, rather than copying them to the same address in a leaky fashion and linking it to itself, infinitely.
You also need to free() all memory that you have dynamically allocated once you're finished using it, e.g. through a sweep of the linked list in a 'destructor' function or at the end of your program. Otherwise you're leaking memory. This is a basic error and, even in cases where it doesn't stop a program from working, wastes users' RAM, which they rightly dislike!
I highly recommend studying pointers and dynamic allocation some more before continuing trying to write code like this.

Does passing "pointer to structure" to a function create local copies of it in C?

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.

Returning local pointer

My question is an extension of this: Returning pointer to a local structure
I wrote the following code to create an empty list:
struct node* create_empty_list(void)
{
struct node *head = NULL;
return head;
}
I just read that returning pointers to local variables is useless, since the variable will be destroyed when the function exits. I believe the above code is returning a NULL pointer, so I don't think it's a pointer to a local variable.
Where is the memory allocated to the pointer in this case. I didn't allocate any memory on the heap, and it should be on the stack, as an automatic variable. But what happens when the code exits (to the pointer), if I try to use it in the program, by assigning this pointer some pointees / de-referencing and alike?
struct node* create_empty_list(void)
{
struct node *head = NULL;
return head;
}
is equivalent to:
struct node* create_empty_list(void)
{
return NULL;
}
which is perfectly fine.
The problem would happen if you had something like:
struct node head;
return &head; // BAD, returning a pointer to an automatic object
Here, you are returning the value of a local variable, which is OK:
struct node* create_empty_list()
{
struct node* head = NULL;
return head;
}
The value of head, which happens to be NULL (0), is copied into the stack before function create_empty_list returns. The calling function would typically copy this value into some other variable.
For example:
void some_func()
{
struct node* some_var = create_empty_list();
...
}
In each of the examples below, you would be returning the address of a local variable, which is not OK:
struct node* create_empty_list()
{
struct node head = ...;
return &head;
}
struct node** create_empty_list()
{
struct node* head = ...;
return &head;
}
The address of head, which may be a different address every time function create_empty_list is called (depending on the state of the stack at that point), is returned. This address, which is typically a 4-byte value or an 8-byte value (depending on your system's address space), is copied into the stack before the function returns. You may use this value "in any way you like", but you should not rely on the fact that it represents the memory address of a valid variable.
A few basic facts about variables, that are important for you to understand:
Every variable has an address and a value.
The address of a variable is constant (i.e., it cannot change after you declare the variable).
The value of a variable is not constant (unless you explicitly declare it as a const variable).
With the word pointer being used, it is implied that the value of the variable is by itself the address of some other variable. Nonetheless, the pointer still has its own address (which is unrelated to its value).
Please note that the description above does not apply for arrays.
As others have mentioned, you are returning value, what is perfectly fine.
However, if you had changed functions body to:
struct node head;
return &head;
you would return address (pointer to) local variable and that could be potentially dangerous as it is allocated on the stack and freed immediately after leaving function body.
If you changed your code to:
struct node * head = (struct node *) malloc( sizeof( struct node ) );;
return head;
Then you are returning value of local value, that is pointer to heap-allocated memory which will remain valid until you call free on it.
Answering
Where is the memory allocated to the pointer in this case. I didn't
allocate any memory on the heap, and it should be on the stack, as an
automatic variable. But what happens when the code exits (to the
pointer), if I try to use it in the program, by assigning this pointer
some pointees / de-referencing and alike?
There is no memory allocated to the pointer in your case. There is memory allocated to contain the pointer, which is on the stack, but since it is pointing to NULL it doesn't point to any usable memory. Also, you shouldn't worry about that your pointer is on the stack, because returning it would create a copy of the pointer.
(As others mentioned) memory is allocated on the stack implicitly when you declare objects in a function body. As you probably know (judging by your question), memory is allocated on the heap by explicitly requesting so (using malloc in C).
If you try to dereference your pointer you are going to get a segmentation fault. You can assign to it, as this would just overwrite the NULL value. To make sure you don't get a segmentation fault, you need to check that the list that you are using is not the NULL pointer. For example here is an append function:
struct node
{
int elem;
struct node* next;
};
struct node* append(struct node* list, int el) {
// save the head of the list, as we would be modifying the "list" var
struct node* res = list;
// create a single element (could be a separate function)
struct node* nn = (struct node*)malloc(sizeof(struct node));
nn->elem = el;
nn->next = NULL;
// if the given list is not empty
if (NULL != list) {
// find the end of the list
while (NULL != list->next) list = list->next;
// append the new element
list->next = nn;
} else {
// if the given list is empty, just return the new element
res = nn;
}
return res;
}
The crucial part is the if (NULL != list) check. Without it, you would try to dereference list, and thus get a segmentation fault.

Delete struct from stack memory

I have a linked list struct, i want to pass one node (another struct) pointer to a function (the node is part of the linked list, but i'm passing the node seperately to a deleter function
I want it to copy the next node data into itself (overriding its data), and to delete the next node, thus deleting itself (this part is working)..
I made it check whether the passed node is the last node in the list, and if so, to delete itself.
I don't know how to delete structs from the stack (i know i can malloc() and free() it using the heap memory).
#include <stdlib.h>
#include <stdio.h>
typedef struct {
int data;
struct node * next;
}node;
typedef struct {
struct node * head;
}linked_list;
void print_list(linked_list * list) {
node *current = list->head;
while (current) {
printf("Current node has %d\n",current->data);
current = current->next;
}
}
void delete_node(node * n) {
node * next = n->next;
if (next) {
n->data = next->data;
n->next = next->next;
}
else {
*n = NULL; /*This of course won't compile because assigning void* (null) to node variable
but if i make n point to NULL, nothing will happen because i'm inside a function
and the pointer is duplicated (the passed pointer will still work) */
}
}
void main(){
node first;
node second;
first.data = 1;
first.next = &second;
second.data = 2;
second.next = NULL;
linked_list l;
l.head = &first;
print_list(&l);
delete_node(&second);
print_list(&l);
}
As others have said, you can't.
If you want to be able to store both allocated (by malloc) and non-allocated (static or automatic) storage objects in your list and have a "delete" function that removes objects from the list and frees them, you need to store as part of each list member a flag indicating whether it's in allocated storage or not, and only free the ones which are.
Also note that you'll be in big trouble if the lifetime of the structure with automatic storage ends before you remove it from the list! If dealing with this is confusing at all for you, then you would probably be better-off just using allocated storage (malloc) for all list members.
You can't :)
On most computer architectures, local variables are either allocated directly on a CPU register or on the stack. For local variables allocated on the stack, the top of the stack (the same stack that is used to hold the return addresses of function calls) is manipulated to make space for them when a function enters, and it is restored to "release" the memory when the function exits. All this stack management is handled automatically by the compiler.
You can use the 'free' operator for freeing / deleting a malloc assigned object in the memory. For that, in your code you can write :
free(n);

Resources