I'm just scratching the surface with nodes and linked lists, so I've been trying to create a linked lists that prints out nodes from 1-10. However, it's full of problems. The program gives me a runtime error and segmentation fault, I also have errors when running valgrind.
The comments are more for me, to show that I (hopefully) know what each command is doing
#include <stdio.h>
#include <stdlib.h>
int main(void) {
typedef struct node {
int value;
struct node* next;
}
node;
//creates nodes for head, tmp, content
node* head = NULL;
node* tmp = NULL;
node* content = NULL;
head->next = content; //head node points to content
for (int i = 1; i <= 10; i++) {
content = malloc(sizeof(node)); //creates new node
content->value = i; //node data becomes i
tmp->next = content; //tmp node points to content node
tmp = tmp->next; //tmp node becomes next content node
content->next = NULL; //content node points to null
printf("%i ", content->value); //see node value
}
while (head != NULL) {
node* temp = head;
head = head->next;
free(temp);
}
return 0;
}
Ok, so let's break this down
section by section
#include <stdio.h>
#include <stdlib.h>
int main(void) {
// Data section
typedef struct node {
int value;
struct node* next;
}
node;
node* head = NULL; // a pointer to what will be the head of the list
node* content; // a utility pointer
node* temp; // a utility pointer
int i; // iteration var
// Code Section
for (i = 1; i <= 10; i++) {
if (head == NULL) {
// The list is empty when this condition triigers
// we initialize the first node and assign head to point to it
head = (node*)malloc(sizeof(node)); // allocate memory to the pointer. Also make sure the memory pointed to is of a node type
// This is important because it will allow us use -> operator to assign values to the pointed
// at memory
head -> value = i; // assign the value i to the value field of the pointed to memory
head -> next = NULL; // assign the next pointer of the pointed to memory to NULL
} else {
// iterate over the list till we reach the end.
// Once we do, assign more memory at the end, assign the memory a value and make it's next pointer be NULL
content = head;
while (content -> next != NULL) {
content = content -> next;
}
content -> next = (node*)malloc(sizeof(node));
content -> next -> value = i;
}
}
while (head != NULL) {
temp = head;
printf("Node data: %d\n", temp -> value);
head = head->next;
free(temp);
}
return 0;
}
// Data section
typedef struct node {
int value;
struct node* next;
}
node;
node* head = NULL; // a pointer to what will be the head of the list
node* content; // a utility pointer
node* temp; // a utility pointer
int i; // iteration var
When I learnt to program in C if you didn't declare the vars your function used upfront at the top of the function, the compiler would complain. For some reason it works now.
When you declare something as a pointer, you are only declaring it. You cannot assign values to it before you allocate memory to the pointer.
// Code Section
for (i = 1; i <= 10; i++) {
if (head == NULL) {
// The list is empty when this condition triigers
// we initialize the first node and assign head to point to it
head = (node*)malloc(sizeof(node)); // allocate memory to the pointer. Also make sure the memory pointed to is of a node type
// This is important because it will allow us use -> operator to assign values to the pointed
// at memory
head -> value = i; // assign the value i to the value field of the pointed to memory
head -> next = NULL; // assign the next pointer of the pointed to memory to NULL
} else {
// iterate over the list till we reach the end.
// Once we do, assign more memory at the end, assign the memory a value and make it's next pointer be NULL
content = head;
while (content -> next != NULL) {
content = content -> next;
}
content -> next = (node*)malloc(sizeof(node));
content -> next -> value = i;
}
}
The right way to allocate memory and make sure the allocate memory is of a specific type is using malloc
and cast it to the appropriate type. As you can see in some lines like content -> next = (node*)malloc(sizeof(node));
. Ensuring the type of the memory allocated is done with the typecast (node*)
What you were doing wrong
head->next = content;
is wrong. head
at the time of this statement in your code is NULL
. It doesn't have a next
pointer that you can point to anything.tmp->next = content;
same as abovecontent = malloc(sizeof(node));
works best with the typecast I outlined abovemalloc
can fail for a variety of reasons. It returns a NULL
which you should check for.head
the head of your list