Building Linked Lists in C From Scratch with an Interactive Colab
Introduction
If pointers in C feel abstract, linked lists are where they finally become real.
A linked list is one of the first data structures where you stop thinking about variables as isolated boxes and start thinking about memory as connected pieces.
This walkthrough builds linked lists step-by-step — from the smallest C program all the way to traversing and joining lists — using simple examples.
1. The Smallest Possible C Program
Everything starts with a tiny executable:
#include <stdio.h>
int main() {
printf("hello from C\n");
return 0;
}
Key ideas:
-
main()is the entry point -
printf()prints text -
return 0means success
Compile and run:
gcc main.c -o main
./main
2. Creating a Struct
A linked list node is just a struct with data and a pointer.
Start simple:
struct point {
int x;
int y;
};
Now you can create variables that group multiple fields together:
struct point p;
p.x = 3;
p.y = 4;
Think of structs as custom types.
3. Using typedef
Typing struct point repeatedly gets annoying.
So we use:
typedef struct point {
int x;
int y;
} point;
Now you can write:
point p;
instead of:
struct point p;
Cleaner and more readable.
4. Pointers to Structs and the -> Operator
Pointers become much easier once they’re attached to structs.
point *ptr = &p;
Access fields with:
ptr->x = 7;
ptr->y = 9;
This is shorthand for:
(*ptr).x
The arrow operator is everywhere in linked lists.
5. Dynamic Memory with malloc
Now memory moves from the stack to the heap.
point *p = malloc(sizeof(point));
This allocates memory while the program is running.
Then:
p->x = 1;
p->y = 2;
And finally:
free(p);
Rule:
-
mallocallocates memory -
freereleases memory
Forget free, and memory leaks.
6. Your First Linked List Node
Now combine everything:
typedef struct ll_text {
char *text;
struct ll_text *next;
} ll_text;
This is the core linked list idea.
A node contains:
-
Data
-
A pointer to another node
The magic is:
struct ll_text *next;
The struct points to another version of itself.
That creates the chain.
7. Creating One Node
ll_text *node = malloc(sizeof(ll_text));
node->text = strdup("hello");
node->next = NULL;
Important:
node->next = NULL;
NULL means:
“This is the end of the list.”
Without it, traversal becomes unsafe.
8. Connecting Two Nodes
Now create links:
a->next = b;
Visual model:
A --> B --> NULL
Example:
printf("%s -> %s -> NULL\n", a->text, a->next->text);
You are literally walking pointers through memory.
9. Traversing a Linked List
Traversal is the core operation.
ll_text *curr = a;
while (curr != NULL) {
printf("%s -> ", curr->text);
curr = curr->next;
}
This loop means:
-
Use current node
-
Move to next node
-
Stop at
NULL
Visual flow:
curr
↓
A -> B -> C -> NULL
Then:
A printed
curr moves to B
B printed
curr moves to C
C printed
curr moves to NULL
Loop ends.
10. Writing a Node Constructor
Instead of repeating allocation logic:
ll_text *make_node(char *word) {
ll_text *node = malloc(sizeof(ll_text));
node->text = strdup(word);
node->next = NULL;
return node;
}
Now you can do:
ll_text *node = make_node("hello");
This pattern appears constantly in systems programming.
11. Joining Lists
Here’s an important example:
ll_text *join_lists(ll_text *list1, ll_text *list2) {
ll_text *newlist = malloc(sizeof(ll_text));
newlist->text = strdup(list1->text);
newlist->next = list2;
return newlist;
}
This is subtle.
It only copies:
- ONE node from
list1
Then connects it to list2.
It does NOT clone the full first list.
That distinction matters heavily on exams and interviews.
12. Appending Lists Properly
A more realistic append operation:
while (curr->next != NULL) {
curr = curr->next;
}
curr->next = list2;
This walks to the end of list1 and attaches list2.
Visual result:
A -> B -> X -> NULL
This is true list concatenation.
13. The Most Common Linked List Bug
Forgetting:
node->next = NULL;
Uninitialized pointers contain garbage memory.
Traversal may:
-
crash
-
loop forever
-
corrupt memory
Always terminate lists explicitly.
14. The Mental Model That Makes Linked Lists Click
A linked list node contains:
[data] + [pointer to next node]
Traversal always follows the same pattern:
curr = head;
while (curr != NULL) {
use curr
curr = curr->next
}
Core memory concepts involved:
-
structs
-
pointers
-
heap allocation
-
dynamic memory
-
self-referential types
Linked lists are less about the data structure itself and more about learning how memory actually works in C.
Once this clicks, trees, graphs, stacks, queues, and operating systems become much easier to understand.