Linked list node memory allocation - c

In creating a linked list we make a node structure and it consists of both data and a pointer to the next node. Later when we make a function to append elements onto the linked list, we make a temporary node to store the inputted data.
Let’s consider the following program-
#include<stdio.h>
struct node
{
int data;
struct node* link;
}
struct node* root=NULL;
void main(append)
{
struct node* temp;
temp= (struct node*)malloc(sizeof(struct node))
.....
}
My first question set:
In line 11, why do we need to mention (struct node*) before the malloc function?
What is the significance of that?
My second question set:
If we are making a doubly linked list which would have a node structure consisting of 2 pointers (for next and previous node), would we also initialize a pointer (for traversing the list) of the struct node type?
Is there a different way to initialize the pointer in that case?

The significance is to make bugs in your program,
The malloc will return void* and when you assign to your struct somthing* it will convert automaticlly.

You simply don't cast the result of malloc as it returns void* . There is one fine explanation here
A better solution might be :
struct node *temp;
temp = malloc(sizeof *temp);

why do we need to mention '(struct node*)' before the malloc function,
what is the significance of that?
By writing (struct node*) before the malloc function, you are type-casting the return value to the specified type. The cast here is optional and often frowned upon.
if we are making a doubly linked list which would have a node
structure consisting of 2 pointers(...
When making a doubly linked list, you should declare something like:
struct node {
int data;
struct node *next;
struct node *previous;
};
You can allocate space for a node by using the malloc function. The next and previous pointers are again pointers to struct nodes. Call malloc again to allocate space for the next element. For the first node, the previous should be NULL and for the last node, next should be NULL. Here is one implementation.

This is the because the return type of malloc is void*. (struct node*) is a cast using which you tell the compiler that you want to treat the value returned by malloc as a pointer to struct node.
For double linked list you can use,
struct node
{
int data;
struct node *next,*prev;
};
int main()
{
struct node *new_node=(struct node *)malloc(sizeof(node));
}

malloc returns the void pointer(can be checked and verified at the header ), and so the type casting is necessary while assigning it to the other type of variable.
Request you to read at the link https://www.tutorialspoint.com/cprogramming/c_type_casting.htm

Related

Freeing a struct

I have a linked list struct on me, and I used a node struct to help me store data and know where each node is pointing to. In the creation of my list, I did this:
struct list {
struct node *Head;
struct node *Tail;
}
struct node{
int val;
struct node * next;
}
struct list create_list(){
struct list new_list;
new_list = malloc(sizeof(struct list));
}
Then, when I am trying to free the list that I malloced for, I did this
void free_list(struct list linked_list){
free(linked_list);
}
However, I realize that I may have malloced wrong, because when you malloc, you need to assign it to a pointer. When I want to free the linked_list that I originally malloced for, nothing really changes.
I think this may be because the linked_list that I sent into free() is not a pointer, thus no changes have been made. I tried adding & and * to it, but I end up getting errors....
Any tips or help is appreciated.
Edit:
Fixed Typo on the struct list.
This is hw, so I cannot change the parameters of the functions, which is what is giving me a hard time freeing the linked list I made. This is because the function free_list() cannot change its parameter into a pointer linked list, so I don't know exactly what to do.
I will also take note of when I am mallocing for the linked list in the create_list function.
Yay for passing the linked list around by value rather than on the heap for something that small.
Is this more like what you want:
struct list create_list(){
struct list new_list = { NULL, NULL };
return list;
}
void free_list(struct list linked_list){
struct node *next;
for (struct node *node = linked_list.Head; node; node = next;)
{
temp = node->next;
free(node);
}
}
Thus freeing only the list nodes that were allocated with malloc().

Creating a link in linked lists in C

Here is the code to create a link in the list which i read off the internet to try understand linked lists in c:
//insert link at first location
void insertFirst(int key, int data) {
//create a link
struct node *link = (struct node*) malloc(sizeof(struct node));
link->key = key;
link->data = data;
//point it to old first node
link->next = head;
//point first to new first node
head = link;
}
I am really not understanding how the following line works as a whole:
struct node *link = (struct node*) malloc(sizeof(struct node));
and more specifically:
(struct node*)
because my understanding is that the asterisk must come before the pointer name and yet its at the end of the struct name. Please correct me if I'm wrong and please if you can, explain how this works?
Casting the return value of malloc is unnecessary.
As per standard 7.22.3.4
The malloc function returns either a null pointer or a pointer to the
allocated space.
You should check its return value to know whether it succeeded or not.
What malloc does?
The malloc function allocates space for an object whose size is specified by size and whose value is indeterminate.
my understanding is that the asterisk must come before the pointer name and yet its at the end of the struct name
Here you are not dereferencing anything. Rather you are typecasting. (which is again I would repeat that unnecessary).
struct node* here is a type of the pointer variable. Same way int or double is a type, this is also a type.
Assume you have to create database of a students having some entities.
struct node
{
int id;
char name [100];
};
Next thing,
struct node *link = (struct node*) malloc(sizeof(struct node));
How above line works ? you need to create one node or memory, So how will you create it, use malloc(). Next things how much memory you are going to create , equal to total size of your data members of structure, so for that its using
struct node *link = malloc(sizeof(struct node));
here link is nothing but name of dynamic memory we created to put some data into that. once memory is created put some data into memory.
scanf("%d %s\n",&link->id,link->name);
similarly you can do above task no of times.
typecasting is not compulsory or not advised to do. So below statement is correct.
struct node *link = malloc(sizeof(struct node));
In order to create a linked list you have to allocate the units -in your case :
struct node
so either you pre-allocate the memory for the list or dynamically allocate them every time you add a node to the list, the memoery for the node has to be recruited from somewhere, in this case - malloc does that.
Hope that helps

pointer to pointers for singly linked list in C [duplicate]

This question already has answers here:
What is the reason for using a double pointer when adding a node in a linked list?
(15 answers)
Closed 9 years ago.
I have a question about signly linked lists in C. I've created a linked list with the code shown below :
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node* next;
};
struct node *mknode(int data)
{
struct node* np=malloc(sizeof(struct node));
np->data=data;
np->next=NULL;
return np;
}
struct node * insert (struct node* list,int data)
{
struct node *np;
struct node*curr=list;
struct node* prev=NULL;
np=mknode(data);
for(;curr &&data<curr->data;curr=curr->next )
prev=curr;
np->next=curr;
if(prev)
prev->next=np;
else
list=np;
return list;
}
int main()
{
struct node* head;
head=malloc(sizeof(struct node));
head=insert(head,7);
head=insert(head,2);
head=insert(head,4);
printf("%d",head->data);
printf("%d",head->next->data);
printf("%d",head->next->next->data);
return 0;
}
However,While I search on internet, I've realized that, the double pointer is used for creating linked list instead of a normal pointer.I mean, struct node **list , not struct node * list . I wonder why ? Which one is correct , and If both of them is true , what is the differences between them, I used my implementation with the sample main I wrote here, and it works fine but I dont know why should I use pointer to pointers ? Thanks in advance.
The reason some people use a pointer to a pointer is so that the nodes can be updated without returning a new pointer. In your example, if you wanted to change the head pointer, you would have to create a new pointer and then make head equal to that pointer. With the double pointer, you only have to free the space that the second pointer points to, and then update the second pointer to your new data structure, which keeps your original head pointer
I just use the single pointer in my implementations.
Read here, In this way you can change elements without creating new ones.
What is the reason for using a double pointer when adding a node in a linked list?
Given
struct node { int x; };
struct node **pplist;
struct node *plist;
pplist is a pointer to a pointer to a struct node, while plist is a pointer to a struct node. To change x, you would need to write
*pplist->x = 3;
plist->x = 4;
You would use a pointer to a pointer if you wanted the same variable to point to, say, different lists, or if you wanted to pass a pointer to a function with a side-effect of changing that pointer.
This looks perfectly fine to me.
All a pointer is, is a memory address to somewhere. A double pointer is just a memory address to another memory address which points to some data.
Maybe you can post where you saw node **list and we can explain it better but for now, your code looks good.
it is a bit of naturally, if you call "head = NULL; insert(&head, data);" that then head points to the first element. All functions, that supose to change the content, should be called indirectly.
BUT: this is a matter of coding convention. Some like it hot, some like it cold. The problem with head=insert(head, data); is, that head is unusable, when you forget "head="

How to declare a linked list in c

struct node {
int data;
struct node *next,*prev;
};
void insert(struct node *head,int data){
if(head == NULL){
head = (node *)malloc(sizeof(node));
--- code continues-----
I just want to know the difference between
head = (node *)malloc(sizeof(node)); and struct node *head = malloc(sizeof(struct node));
And if I pass **head as a parameter of the insert function what does it do ?
The difference between:
head = (node *)malloc(sizeof(node));
struct node *head = malloc(sizeof(struct node));
is that a C compiler will reject the first and allow the second, but a C++ compiler will accept the first and reject the second.
In C, the code shown does not create a type name node when you define or declare struct node. You would need to add typedef struct node node; in the C source. C++ automatically creates the type name node from the definition of struct node. (A C++ compiler rejects the second because of the implicit cast from void * to struct node *; C++ does not allow that, and would require struct node *head = (struct node *)malloc(sizeof(struct node));)
And if I pass **head as a parameter of the insert function, what does it do?
You'd have to adjust the body of the function, but it would allow you to change the location of the head of the list in the calling function.
The answer for your first question is:
head=(node *)malloc(sizeof(node));
malloc() returns a pointer of type void so here you are explicitly converting it to a pointer of type node .But remember, in C a pointer of type void() converts implicitly into the type of pointer that it is assign to. So if you write like:
head=malloc(sizeof(node));
It will stil work correctly. But with the C++ compiler it is not the case, In C++ pointer of type void is not implicitly cast to the type of pointer that it it assign to.
Also to answer your question,
void insert(struct node *head,int data)
If you pass **head as parameter it will show an error declaring that the type of operator is not matched. This is because you had declared it as struct node *head not as struct node **head.
If you type in
typedef struct node{
int data;
struct node *next, *prev;
} node;
the compiler will accept your head = (node *)malloc(sizeof(node)); code. Remember that typedef allows you to use the struct the same way it's used in C++.
Technically there isn't a difference between sizeof(node) and sizeof(struct node) (at least in C++), since both will return the size of the struct.
In C however it's mandatory to write struct node, just like it's mandatory to write struct node when declaring a variable of that type, simply because there is no type node.
C only understands primitives (int, char, long) and custom types declared with struct. Every C compiler is very strict with this keyword struct and assumes you're talking about a variable if you forget it.
Regarding your second question: You can't. You can't pass a pointer to a pointer to a function, which only accepts a regular pointer, unless you cast it. In that case however, it will point to a completely arbitrary position on the stack (where your pointer is located) and probably make your program crash.
create (struct node **p)
{
struct node *temp,*q;
int n;
printf("enter the length of link list");
scanf("%d".&n);
while(n>0)
{
if(*p == NULL)
{
*p=(struct node*)malloc(sizeof(struct node*));
printf("enter the element");
scanf("%d".&((*p)->data));
(*p)->next=NULL;
}
else
q=*p;
while(q->next=NULL)
q=q->next;

how to use a pointer inside struct in C

I have a two struct, one is linked list.
typedef struct Mark{
int people;
Node *nodeyy;
}Mark
typedef struct Node{
struct node next;
int value;
}Node
if i allocated memory for a node, let say
Node *node1=malloc( sizeof(struct Node));
And I also allocated memory for a bookmark, let say
Mark *mark1=malloc( sizeof(struct Mark));
I want to make the pointer nodeyy in the mark1 points to the same thing as node1, how can i do that?
I think that
mark1->nodeyy=node1;
is definitely wrong.
change the int* in struct Mark to Node*
typedef struct Mark{
int people;
Node *nodeyy;
}Mark
then you can do
mark -> nodeyy = (Node *) malloc(sizeof(Node))
its correct now:
You will have to initialize the pointer or point it to an existing variable that you know won't go out-of-scope. BUT since node1 is dynamically allocated, you're just assigning one pointer to another, this creates a sort of reference to the newly allocated memory pointed by node1.
mark1->nodeyy = node1;
After this statement, mark1->nodeyy and node1 point to the memory location returned by the malloc(sizeof(Node)).

Resources