I created a structure for a linked list node in C as follows.
struct node
{
int data;
struct node *next;
} *START = NULL;
Then when I need to access the properties of the structure, I create a pointer to structure as follows.
struct node *node1;
node1 -> data = 12;
node1 -> next = NULL;
I want to know if we can use
struct node node1
instead of the current declaration and what changes would that make in the program.
Also, I want to know why *START=NULL is outside the structure and what its data type is ?
You need to allocate the memory for the struct. Here you have a simple function which appends the node to the end of the list
struct node
{
int data;
struct node *next;
} *START = NULL;
struct node *append(int data)
{
struct node *node1 = malloc(sizeof(*node1));
struct node *list = START;
if(node1)
{
node1 -> data = data;
node1 -> next = NULL;
if(list)
{
while(list -> next)
{
list = list -> next;
}
list -> next = node1;
}
else
{
START = node1;
}
}
return node1;
}
START is the variable of type pointer to the struct node.
struct node *node1;
node1 -> data = 12;
node1 -> next = NULL;
First, the above code doesn't initialize node1 to a valid memory address. It merely creates a pointer called node1 which can take the address of a variable of struct node type which hasn't been properly initialized.
You need to change the code to the following.
struct node *node1 = (struct node*)malloc(sizeof(struct node));
node1 -> data = 12;
node1 -> next = NULL;
The above will allocate memory for struct node type and initialize node1 with the address of the allocated memory.
Now let's get to your questions.
I want to know if we can use
struct node node1
instead of the current declaration and what changes would that make in the program.
You can use the above declaration in your program, but it will create node1 on stack rather than on heap. Probably this is not the behaviour you want since the variable made on stack has the lifetime of the scope in which it's created. In your case I assume you want to create a linked list (or similar structure), therefore you need the list to be accessible even after the function in which the appending happens returns.
Anyway, if you created the variable on stack you can simply use . operator to access structure members.
struct node node1;
node1.data = 12;
node1.next = NULL;
Also, I want to know why *START=NULL is outside the structure and what
its data type is?
It simply defines a pointer variable named START that can point to struct node and initialize it with NULL.
[...] when I need to access the properties of the structure, I create
a pointer to structure as follows.
struct node *node1;
node1 -> data = 12;
node1 -> next = NULL;
Not exactly. You have declared node1 as a variable of type struct node *, but you have not created a pointer, in the sense that you have not given that variable a value that points to any structure. Subsequently attempting to access a struct node via that variable's (indeterminate) value therefore produces undefined behavior. Among the more likely outcomes are that your program crashes or that unexpected changes are made to random objects in its memory.
To be able to use node1 to access a struct node as you show, you first need to assign it to point to one (or at least to memory that can be made to contain one). You can do that either by assigning it the address of an existing struct node or by allocating memory sufficient for a struct node and assigning its address to node1. More on those alternatives later.
I want to know if we can use
struct node node1
instead of the current declaration and what changes would that make in
the program.
You definitely can declare node1 as a struct node instead of as a pointer to one. In the scope of such a declaration, you would access its members via the direct member-access operator (.) instead of via the indirect one (->):
node1.data = 12;
node1.next = NULL;
Furthermore, one of the ways to obtain a pointer to a struct node would be to use the address-of operator (&) to obtain that structure's address:
struct node *node_ptr = &node1;
HOWEVER, the lifetime of the node1 object declared that way ends when control passes out of the innermost block in which the declaration appears (if any), any pointers to it notwithstanding. As such, that usually is not what you want for a linked-list node.
For linked-list applications (among others), one generally wants an object whose lifetime doesn't end until you say it should do, and that can be achieved by dynamically allocating memory for the structure. For example,
struct node *node_ptr = malloc(sizeof(*node_ptr));
The allocated memory remains allocated until you explicitly free() it, whether in that scope or in another. Either way, to access the structure members through a valid pointer, one uses the indirect access operator, as in your example:
node_ptr->data = 42;
node_ptr->next = NULL;
or, equivalently, one first dereferences the pointer and then uses the direct member access operator:
(*node_ptr).data = 42;
(*node_ptr).next = NULL;
.
Also, I want to know why *START=NULL is outside the structure and what
its data type is ?
You said that you wrote the code. If you don't know the significance of the *START=NULL part, then what is it doing in your code?
In any event, it is analogous to the *node_ptr = &node1 above. START is declared (at file scope) as a pointer to a struct node, and its initial (pointer) value is assigned to be NULL, which explicitly and testably does not point to any structure.
When do we use structure variable and structure pointer?
Depends on the use case. When you create a structure variable you actually allocate the structure object on the stack. When you use pointer you usally allocate the structure object in heap memory and point to this object via the pointer.
You can resize and deallocate the dynamically allocated structure object whenever you want to, while the static can't be changes in size and it is only destroyed once the scope of it ends (in case of an automatic structure variable).
More details to the difference between static vs. dynamic allocation you can find in the links below the answer.
Which way you choose, depends on what you want to do and how you want to do it.
I want to know if we can use struct node node1 instead of the current declaration and what changes would that make in the program.
That would make node1 a variable of the structure itself; it would not be a pointer to an object of the structure only anymore.
Beside the things mentioned above and others, the access to the members would be different:
node1 . data = 12;
node1 . next = NULL;
Also I want to know why *START=NULL is outside the structure and what it's data type is.
START is of type struct node * (a pointer to struct node) and initialized to NULL. It's definition is outside because it isn't a member, it is a pointer to an object of the structure.
Note that you need to assign a pointer to struct node to point to an object of struct node, but that is not what you did at:
struct node *node1;
node1 -> data = 12;
node1 -> next = NULL;
So, this would invoke undefined behavior.
Allocate memory for the structure:
struct node *node1 = calloc (1, sizeof(*node1));
if (!node1)
{
fputs("Failure at memory allocation for node1!", stderr);
return EXIT_FAILURE;
}
node1 -> data = 12;
node1 -> next = NULL;
Related regarding point 1.:
What and where are the stack and heap?
Stack variables vs. Heap variables
Why would you ever want to allocate memory on the heap rather than the stack?
Which is faster: Stack allocation or Heap allocation
Related
I've been searching around for a good while now on google and a few text books and I can't seem to understand why it is, when building a linked list, that the nodes need to be pointers.
Eg. If i have a node defined as:
typedef struct Node{
int value;
struct Node *next;
} Node;
why is it that in order to create a linked list, I would say:
Node *a = malloc(sizeof(Node));
Node *b = malloc(sizeof(Node));
a->value = 1;
b->value = 2;
a->next = b;
b->next = NULL;
rather than:
Node a, b;
a.value = 1;
b.value = 2;
a.next = &b;
b.next = NULL;
To my understanding, the list will still be able to be referenced and traversed as normal, the only difference is the use of the dot, ampersand syntax rather than the arrow?
You can create the list in a way that you mentioned.
But you must care for the life time of the list members. If your
Node a, b;
are in scope of a function then these are lost after the return of that function.
When you use pointers then you usually use the heap and the instances live until they are deleted.
Your first example will not work. You are declaring two Node pointers. However, since you do not initialize these to anything, it is illegal to deference them, since they don't point to anything. You must first use something like malloc to declare memory for them to point to, or assign them to a previously declared local variable. However, you must also remember to call free when you are done with the memory.
In the second example, you are declaring two Node variables, which you use to store instances of the Node. These will be allocated on the stack if they are local variables, and they will live for as long as they are in scope. They hold valid memory, and thus you can use them in the way you have demonstrated.
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;
}
}
Feel free to edit the title if it doesn't make sense. So I've been using malloc for a while without really being completely sure of how it works. If I create an int pointer and set it equal to malloc(10*sizeof(int), I figure that it allocates a block in memory of 10 times the size of one int, then returns the starting address of this allocation, but nothing is actually initialized within that memory yet. Am I OK so far?
Now say I create a struct for linked list nodes like this:
typedef struct node_ {
int data;
struct node_ *next;
} Node;
and then have a create linked list function:
Node* LLCreate(int data) {
Node *head = malloc(sizeof(Node));
if ( head != NULL) {
head->next = NULL; // don't get how malloc created `next`
head->data = data; // or `data`
}
return head;
}
What I don't get, and can't seem to google appropriately, is, if head is just the starting location in memory of an empty block of size Node, and not an actual variable, how does it have the local variables of next and data?
Maybe this is a nonsensical question because I have some fundamental misunderstanding of what's going on here, but if anyone understands what I'm trying to ask and could clear this up for me I'd really appreciate it.
It doesnt have local variables like next and data.
next and data are just used to calculate the address relative to from where node is pointing.
When you do node->data then the address is calculated as address pointed by node + (total bytes required by any metadata for malloc) + 0 because data is the first member of node struct.
And when you do node->next then the address is calculated as address pointed by node + (total bytes required by any metadata for malloc) + sizeof(data) , because next is the second member of the node struct that comes after data member.
I am approaching to use this code for building singly linked list. I am pointing out the lines which get me bit confused .
struct node
{
int data;
struct node *next;
}*start=NULL; // point 1
void creat()
{
char ch;
do
{
struct node *new_node,*current;
new_node=(struct node *)malloc(sizeof(struct node));
printf("\nEnter the data : ");
scanf("%d",&new_node->data); //point 2
new_node->next=NULL; // point 3
if(start==NULL)
{
start=new_node;
current=new_node;
}
else
{
current->next=new_node;
current=new_node;
}
printf("\nDo you want to creat another : ");
ch=getche();
}while(ch!='n');
}
point1: What is the advantage declaring the structure node as a pointer?
point2: scanf("%d",&new_node->data);
Not getting the idea how the data is stored here to the 'data' field in context of pointer and structure?
How Linked lists are different from arrays? Consider the following points :
An array is a static data structure. This means the length of array cannot be altered at run time. While, a linked list is a dynamic data structure.
In an array, all the elements are kept at consecutive memory locations while in a linked list the elements (or nodes) may be kept at any location but still connected to each other.
So considering the purpose of dynamic creation of linked list we do not know how many nodes user will create.
Therefore in this case to allocate memory dynamically, pointers are used.
Using pointers will give you the memory location
for your struct.
The purpose of scanf() is to accept the data and store it into the memory location. Here you are accepting an interger value for your data into struct which is named as new_node. So assume your new_node is something like:
new_node = {int data | struct node *next} Here you want to accept the value for your integer field data
There for the scanf will store what ever value you will type into the address location of new_node's data.
Here "1" represents your new_node->data accepted and "NULL" is
new_node->next the pointer to next node.
0a) pointers only save memory addresses, the compiler relies on your declaration to determine how much memory from that address (from *ptr to *ptr + size) is considered part of the object.
0b) within the struct node, you are saving the address of the 'next' node instead of saving the values of the 'next' node. this means at any time there's only one copy of each node.
1) }*start=NULL; is a short-hand way of declaring a struct node pointer called start with initialized value NULL, which means its pointing at nothing.
2a) Declaring pointers of type struct node lets the compiler know that after the pointer it can expect sizeof(struct node) amount of memory behind it to be readable. Obviously you have to malloc that memory beforehand otherwise errors will occur. Finally, the "ptr->data" is equivalent to "(*ptr).data", which dereferences the pointer and then asks for the data element of the struct node.
2b) the form of
int x;
scanf("%d",&x);
passes the &x(address of x) to the function, which reads an int and puts it AT address pointed to by &x. so &ptr->data is basically == address of data.
point1: What is the advantage declaring the structure node as a pointer?
You can use pointer to structure as function argument rather than structure itself so as to avoid making copy of struct. As when you pass a struct compiler makes a copy of that struct.
point2: scanf("%d",&new_node->data);
Arrow Operator(->) is used to access members of structures by pointer variable.
Here in above scanf statement new_node is the pointer variable which is accessing member data of the structure.
This operation is similar to the Dot Operator(.) where we access members of structure using ordinary structure variable.
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);