Linked lists are fundamental data structures that provide dynamic memory allocation and efficient insertion/deletion operations. Unlike arrays, linked lists don't require contiguous memory and can grow or shrink during program execution. Understanding linked lists is essential for mastering C programming and forms the foundation for more complex data structures like trees, graphs, and hash tables.
What Is a Linked List?
A linked list is a linear data structure where each element (node) contains:
- Data: The actual value stored
- Pointer: Address of the next node in the sequence
Singly Linked List: âââââââââââ âââââââââââ âââââââââââ â data: 10 âââââ¶â data: 20 âââââ¶â data: 30 âââââ¶ NULL â next: ââŒâââ â next: ââŒâââ â next: ââŒâââ âââââââââââ âââââââââââ âââââââââââ Head Tail
Types of Linked Lists
- Singly Linked List: Each node points to the next node
- Doubly Linked List: Nodes point to both next and previous nodes
- Circular Linked List: Last node points back to first node
1. Singly Linked List Implementation
Basic Node Structure:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
// Node structure
typedef struct Node {
int data;
struct Node *next;
} Node;
Core Operations:
// Create a new node
Node* createNode(int data) {
Node *newNode = (Node*)malloc(sizeof(Node));
if (!newNode) {
printf("Memory allocation failed!\n");
return NULL;
}
newNode->data = data;
newNode->next = NULL;
return newNode;
}
// Insert at beginning
void insertAtBeginning(Node **head, int data) {
Node *newNode = createNode(data);
if (newNode) {
newNode->next = *head;
*head = newNode;
}
}
// Insert at end
void insertAtEnd(Node **head, int data) {
Node *newNode = createNode(data);
if (!newNode) return;
if (*head == NULL) {
*head = newNode;
return;
}
Node *current = *head;
while (current->next != NULL) {
current = current->next;
}
current->next = newNode;
}
// Insert at position (0-based index)
void insertAtPosition(Node **head, int data, int position) {
if (position < 0) return;
if (position == 0) {
insertAtBeginning(head, data);
return;
}
Node *current = *head;
for (int i = 0; i < position - 1; i++) {
if (current == NULL) return; // Position out of bounds
current = current->next;
}
if (current == NULL) return;
Node *newNode = createNode(data);
if (newNode) {
newNode->next = current->next;
current->next = newNode;
}
}
// Delete from beginning
int deleteFromBeginning(Node **head) {
if (*head == NULL) {
printf("List is empty!\n");
return -1;
}
Node *temp = *head;
int data = temp->data;
*head = (*head)->next;
free(temp);
return data;
}
// Delete from end
int deleteFromEnd(Node **head) {
if (*head == NULL) {
printf("List is empty!\n");
return -1;
}
if ((*head)->next == NULL) {
int data = (*head)->data;
free(*head);
*head = NULL;
return data;
}
Node *current = *head;
while (current->next->next != NULL) {
current = current->next;
}
int data = current->next->data;
free(current->next);
current->next = NULL;
return data;
}
// Delete by value
int deleteByValue(Node **head, int value) {
if (*head == NULL) return -1;
// If head node contains the value
if ((*head)->data == value) {
Node *temp = *head;
*head = (*head)->next;
int data = temp->data;
free(temp);
return data;
}
// Search for the node
Node *current = *head;
while (current->next != NULL && current->next->data != value) {
current = current->next;
}
if (current->next == NULL) {
printf("Value %d not found in list.\n", value);
return -1;
}
Node *temp = current->next;
current->next = temp->next;
int data = temp->data;
free(temp);
return data;
}
// Search for a value
Node* search(Node *head, int value) {
Node *current = head;
while (current != NULL) {
if (current->data == value) {
return current;
}
current = current->next;
}
return NULL;
}
// Get length of list
int getLength(Node *head) {
int count = 0;
Node *current = head;
while (current != NULL) {
count++;
current = current->next;
}
return count;
}
// Get node at index
Node* getNodeAt(Node *head, int index) {
Node *current = head;
int count = 0;
while (current != NULL && count < index) {
current = current->next;
count++;
}
return current;
}
// Reverse the list
void reverseList(Node **head) {
Node *prev = NULL;
Node *current = *head;
Node *next = NULL;
while (current != NULL) {
next = current->next; // Store next node
current->next = prev; // Reverse link
prev = current; // Move prev forward
current = next; // Move current forward
}
*head = prev; // Update head
}
// Display the list
void displayList(Node *head) {
if (head == NULL) {
printf("List is empty.\n");
return;
}
printf("List: ");
Node *current = head;
while (current != NULL) {
printf("%d", current->data);
if (current->next != NULL) {
printf(" -> ");
}
current = current->next;
}
printf(" -> NULL\n");
printf("Length: %d\n", getLength(head));
}
// Free entire list
void freeList(Node **head) {
Node *current = *head;
while (current != NULL) {
Node *temp = current;
current = current->next;
free(temp);
}
*head = NULL;
}
// Main function to demonstrate singly linked list
int main() {
Node *head = NULL;
printf("=== Singly Linked List Demonstration ===\n\n");
// Insert at beginning
printf("Inserting at beginning: 30, 20, 10\n");
insertAtBeginning(&head, 30);
insertAtBeginning(&head, 20);
insertAtBeginning(&head, 10);
displayList(head);
// Insert at end
printf("\nInserting at end: 40, 50\n");
insertAtEnd(&head, 40);
insertAtEnd(&head, 50);
displayList(head);
// Insert at position
printf("\nInserting 25 at position 2:\n");
insertAtPosition(&head, 25, 2);
displayList(head);
// Delete operations
printf("\nDeleting from beginning: %d\n", deleteFromBeginning(&head));
displayList(head);
printf("\nDeleting from end: %d\n", deleteFromEnd(&head));
displayList(head);
printf("\nDeleting value 25: %d\n", deleteByValue(&head, 25));
displayList(head);
// Search
int searchValue = 40;
Node *found = search(head, searchValue);
printf("\nSearching for %d: %s\n", searchValue,
found ? "Found" : "Not found");
// Reverse
printf("\nReversing list:\n");
reverseList(&head);
displayList(head);
// Free memory
freeList(&head);
printf("\nList freed. Head is: %s\n", head ? "not NULL" : "NULL");
return 0;
}
2. Doubly Linked List
Doubly linked lists have pointers to both next and previous nodes, enabling bidirectional traversal.
typedef struct DNode {
int data;
struct DNode *prev;
struct DNode *next;
} DNode;
// Create a new doubly linked list node
DNode* createDNode(int data) {
DNode *newNode = (DNode*)malloc(sizeof(DNode));
if (!newNode) return NULL;
newNode->data = data;
newNode->prev = NULL;
newNode->next = NULL;
return newNode;
}
// Insert at beginning (doubly linked list)
void insertAtBeginningD(DNode **head, int data) {
DNode *newNode = createDNode(data);
if (!newNode) return;
if (*head != NULL) {
(*head)->prev = newNode;
}
newNode->next = *head;
*head = newNode;
}
// Insert at end (doubly linked list)
void insertAtEndD(DNode **head, int data) {
DNode *newNode = createDNode(data);
if (!newNode) return;
if (*head == NULL) {
*head = newNode;
return;
}
DNode *current = *head;
while (current->next != NULL) {
current = current->next;
}
current->next = newNode;
newNode->prev = current;
}
// Delete from end (doubly linked list)
int deleteFromEndD(DNode **head) {
if (*head == NULL) return -1;
if ((*head)->next == NULL) {
int data = (*head)->data;
free(*head);
*head = NULL;
return data;
}
DNode *current = *head;
while (current->next != NULL) {
current = current->next;
}
int data = current->data;
current->prev->next = NULL;
free(current);
return data;
}
// Display forward
void displayForward(DNode *head) {
if (head == NULL) {
printf("List is empty.\n");
return;
}
printf("Forward: NULL");
DNode *current = head;
while (current != NULL) {
printf(" <- %d -> ", current->data);
current = current->next;
}
printf("NULL\n");
}
// Display backward
void displayBackward(DNode *head) {
if (head == NULL) {
printf("List is empty.\n");
return;
}
// Go to last node
DNode *current = head;
while (current->next != NULL) {
current = current->next;
}
printf("Backward: NULL");
while (current != NULL) {
printf(" <- %d -> ", current->data);
current = current->prev;
}
printf("NULL\n");
}
// Free doubly linked list
void freeListD(DNode **head) {
DNode *current = *head;
while (current != NULL) {
DNode *temp = current;
current = current->next;
free(temp);
}
*head = NULL;
}
// Demonstrate doubly linked list
void demoDoublyLinkedList() {
printf("\n=== Doubly Linked List Demonstration ===\n\n");
DNode *head = NULL;
// Insert at beginning
printf("Inserting at beginning: 30, 20, 10\n");
insertAtBeginningD(&head, 30);
insertAtBeginningD(&head, 20);
insertAtBeginningD(&head, 10);
displayForward(head);
displayBackward(head);
// Insert at end
printf("\nInserting at end: 40, 50\n");
insertAtEndD(&head, 40);
insertAtEndD(&head, 50);
displayForward(head);
// Delete from end
printf("\nDeleting from end: %d\n", deleteFromEndD(&head));
displayForward(head);
freeListD(&head);
}
3. Circular Linked List
In a circular linked list, the last node points back to the first node.
typedef struct CNode {
int data;
struct CNode *next;
} CNode;
// Create a new circular linked list node
CNode* createCNode(int data) {
CNode *newNode = (CNode*)malloc(sizeof(CNode));
if (!newNode) return NULL;
newNode->data = data;
newNode->next = newNode; // Points to itself initially
return newNode;
}
// Insert at beginning (circular)
void insertAtBeginningC(CNode **head, int data) {
CNode *newNode = createCNode(data);
if (!newNode) return;
if (*head == NULL) {
*head = newNode;
return;
}
// Find last node
CNode *last = *head;
while (last->next != *head) {
last = last->next;
}
newNode->next = *head;
last->next = newNode;
*head = newNode;
}
// Insert at end (circular)
void insertAtEndC(CNode **head, int data) {
CNode *newNode = createCNode(data);
if (!newNode) return;
if (*head == NULL) {
*head = newNode;
return;
}
// Find last node
CNode *last = *head;
while (last->next != *head) {
last = last->next;
}
last->next = newNode;
newNode->next = *head;
}
// Display circular list
void displayCircular(CNode *head) {
if (head == NULL) {
printf("List is empty.\n");
return;
}
printf("Circular: ");
CNode *current = head;
do {
printf("%d", current->data);
current = current->next;
if (current != head) {
printf(" -> ");
}
} while (current != head);
printf(" -> (back to %d)\n", head->data);
}
// Get length of circular list
int getCircularLength(CNode *head) {
if (head == NULL) return 0;
int count = 0;
CNode *current = head;
do {
count++;
current = current->next;
} while (current != head);
return count;
}
// Free circular list
void freeCircularList(CNode **head) {
if (*head == NULL) return;
// Break the circle first
CNode *last = *head;
while (last->next != *head) {
last = last->next;
}
last->next = NULL;
// Free as normal list
CNode *current = *head;
while (current != NULL) {
CNode *temp = current;
current = current->next;
free(temp);
}
*head = NULL;
}
// Demonstrate circular linked list
void demoCircularLinkedList() {
printf("\n=== Circular Linked List Demonstration ===\n\n");
CNode *head = NULL;
// Insert at beginning
printf("Inserting at beginning: 30, 20, 10\n");
insertAtBeginningC(&head, 30);
insertAtBeginningC(&head, 20);
insertAtBeginningC(&head, 10);
displayCircular(head);
printf("Length: %d\n", getCircularLength(head));
// Insert at end
printf("\nInserting at end: 40, 50\n");
insertAtEndC(&head, 40);
insertAtEndC(&head, 50);
displayCircular(head);
printf("Length: %d\n", getCircularLength(head));
freeCircularList(&head);
}
4. Advanced Linked List Operations
Merge Two Sorted Lists:
Node* mergeSortedLists(Node *list1, Node *list2) {
if (list1 == NULL) return list2;
if (list2 == NULL) return list1;
Node *result = NULL;
if (list1->data <= list2->data) {
result = list1;
result->next = mergeSortedLists(list1->next, list2);
} else {
result = list2;
result->next = mergeSortedLists(list1, list2->next);
}
return result;
}
Detect Cycle (Floyd's Algorithm):
bool hasCycle(Node *head) {
if (head == NULL) return false;
Node *slow = head;
Node *fast = head;
while (fast != NULL && fast->next != NULL) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) {
return true; // Cycle detected
}
}
return false;
}
Find Middle Node:
Node* findMiddle(Node *head) {
if (head == NULL) return NULL;
Node *slow = head;
Node *fast = head;
while (fast != NULL && fast->next != NULL) {
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
Remove Duplicates (Sorted List):
void removeDuplicatesSorted(Node *head) {
if (head == NULL) return;
Node *current = head;
while (current->next != NULL) {
if (current->data == current->next->data) {
Node *temp = current->next;
current->next = temp->next;
free(temp);
} else {
current = current->next;
}
}
}
Remove Duplicates (Unsorted List):
void removeDuplicatesUnsorted(Node *head) {
if (head == NULL) return;
Node *current = head;
while (current != NULL) {
Node *runner = current;
while (runner->next != NULL) {
if (runner->next->data == current->data) {
Node *temp = runner->next;
runner->next = temp->next;
free(temp);
} else {
runner = runner->next;
}
}
current = current->next;
}
}
Rotate List:
Node* rotateRight(Node *head, int k) {
if (head == NULL || head->next == NULL || k == 0) {
return head;
}
// Find length and last node
int len = 1;
Node *last = head;
while (last->next != NULL) {
last = last->next;
len++;
}
// Make it circular
last->next = head;
// Find new head and break
k = k % len;
int steps = len - k;
Node *newLast = head;
for (int i = 1; i < steps; i++) {
newLast = newLast->next;
}
Node *newHead = newLast->next;
newLast->next = NULL;
return newHead;
}
Split List into Two Halves:
void splitList(Node *head, Node **firstHalf, Node **secondHalf) {
if (head == NULL || head->next == NULL) {
*firstHalf = head;
*secondHalf = NULL;
return;
}
Node *slow = head;
Node *fast = head->next;
while (fast != NULL) {
fast = fast->next;
if (fast != NULL) {
slow = slow->next;
fast = fast->next;
}
}
*firstHalf = head;
*secondHalf = slow->next;
slow->next = NULL;
}
5. Generic Linked List (Using void*)
typedef struct GenericNode {
void *data;
size_t dataSize;
struct GenericNode *next;
} GenericNode;
typedef struct {
GenericNode *head;
int size;
} GenericList;
GenericList* createGenericList() {
GenericList *list = (GenericList*)malloc(sizeof(GenericList));
list->head = NULL;
list->size = 0;
return list;
}
void insertGeneric(GenericList *list, void *data, size_t dataSize) {
GenericNode *newNode = (GenericNode*)malloc(sizeof(GenericNode));
newNode->data = malloc(dataSize);
newNode->dataSize = dataSize;
memcpy(newNode->data, data, dataSize);
newNode->next = list->head;
list->head = newNode;
list->size++;
}
void* getGeneric(GenericList *list, int index) {
if (index < 0 || index >= list->size) return NULL;
GenericNode *current = list->head;
for (int i = 0; i < index; i++) {
current = current->next;
}
return current->data;
}
void freeGenericList(GenericList *list) {
GenericNode *current = list->head;
while (current != NULL) {
GenericNode *temp = current;
current = current->next;
free(temp->data);
free(temp);
}
free(list);
}
// Example usage
void demoGenericList() {
GenericList *list = createGenericList();
// Store integers
int intVal = 42;
insertGeneric(list, &intVal, sizeof(int));
// Store doubles
double dblVal = 3.14159;
insertGeneric(list, &dblVal, sizeof(double));
// Store strings
char *strVal = "Hello";
insertGeneric(list, strVal, strlen(strVal) + 1);
// Retrieve and print
printf("Generic list contents:\n");
int *retrievedInt = (int*)getGeneric(list, 2);
printf(" Integer: %d\n", *retrievedInt);
double *retrievedDbl = (double*)getGeneric(list, 1);
printf(" Double: %f\n", *retrievedDbl);
char *retrievedStr = (char*)getGeneric(list, 0);
printf(" String: %s\n", retrievedStr);
freeGenericList(list);
}
6. Practical Applications
Polynomial Representation:
typedef struct Term {
int coefficient;
int exponent;
struct Term *next;
} Term;
Term* createTerm(int coeff, int exp) {
Term *t = (Term*)malloc(sizeof(Term));
t->coefficient = coeff;
t->exponent = exp;
t->next = NULL;
return t;
}
void addTerm(Term **poly, int coeff, int exp) {
if (coeff == 0) return;
Term *newTerm = createTerm(coeff, exp);
if (*poly == NULL || (*poly)->exponent < exp) {
newTerm->next = *poly;
*poly = newTerm;
return;
}
Term *current = *poly;
while (current->next != NULL && current->next->exponent > exp) {
current = current->next;
}
if (current->exponent == exp) {
current->coefficient += coeff;
free(newTerm);
if (current->coefficient == 0) {
// Remove term if coefficient becomes zero
// (implementation omitted for brevity)
}
} else {
newTerm->next = current->next;
current->next = newTerm;
}
}
void displayPolynomial(Term *poly) {
if (poly == NULL) {
printf("0\n");
return;
}
Term *current = poly;
while (current != NULL) {
if (current != poly && current->coefficient > 0) {
printf("+");
}
if (current->exponent == 0) {
printf("%d", current->coefficient);
} else if (current->exponent == 1) {
printf("%dx", current->coefficient);
} else {
printf("%dx^%d", current->coefficient, current->exponent);
}
current = current->next;
}
printf("\n");
}
Term* addPolynomials(Term *p1, Term *p2) {
Term *result = NULL;
while (p1 != NULL || p2 != NULL) {
if (p1 == NULL) {
addTerm(&result, p2->coefficient, p2->exponent);
p2 = p2->next;
} else if (p2 == NULL) {
addTerm(&result, p1->coefficient, p1->exponent);
p1 = p1->next;
} else if (p1->exponent > p2->exponent) {
addTerm(&result, p1->coefficient, p1->exponent);
p1 = p1->next;
} else if (p2->exponent > p1->exponent) {
addTerm(&result, p2->coefficient, p2->exponent);
p2 = p2->next;
} else {
addTerm(&result, p1->coefficient + p2->coefficient, p1->exponent);
p1 = p1->next;
p2 = p2->next;
}
}
return result;
}
void demoPolynomial() {
Term *poly1 = NULL;
Term *poly2 = NULL;
addTerm(&poly1, 5, 3); // 5x^3
addTerm(&poly1, 4, 2); // +4x^2
addTerm(&poly1, 3, 0); // +3
addTerm(&poly2, 2, 4); // 2x^4
addTerm(&poly2, 1, 2); // +1x^2
addTerm(&poly2, 7, 1); // +7x
printf("Polynomial 1: ");
displayPolynomial(poly1);
printf("Polynomial 2: ");
displayPolynomial(poly2);
Term *sum = addPolynomials(poly1, poly2);
printf("Sum: ");
displayPolynomial(sum);
}
7. Performance Comparison
| Operation | Array | Singly Linked List | Doubly Linked List |
|---|---|---|---|
| Access by index | O(1) | O(n) | O(n) |
| Insert at beginning | O(n) | O(1) | O(1) |
| Insert at end | O(1)* | O(n) | O(1) with tail |
| Delete at beginning | O(n) | O(1) | O(1) |
| Delete at end | O(1) | O(n) | O(1) |
| Memory per element | Low | High (pointer overhead) | Higher (two pointers) |
*If array has space; O(n) if resize needed
8. Common Pitfalls and Solutions
// Pitfall 1: Not checking malloc return
Node *node = malloc(sizeof(Node)); // Might return NULL
node->data = 10; // Crash if malloc failed!
// Solution:
Node *node = malloc(sizeof(Node));
if (node == NULL) {
printf("Memory allocation failed!\n");
return;
}
// Pitfall 2: Losing reference to list
Node *head = NULL;
insertAtBeginning(&head, 10);
head = NULL; // Lost the list - memory leak!
// Solution: Always use freeList() before reassigning
// Pitfall 3: Dangling pointers after free
Node *node = head;
free(node);
node->data = 20; // Using freed memory!
// Solution: Set pointer to NULL after free
free(node);
node = NULL;
// Pitfall 4: Not updating head in functions
void badInsert(Node *head, int data) { // Pass by value!
Node *newNode = createNode(data);
newNode->next = head;
head = newNode; // Only modifies local copy!
}
// Solution: Pass pointer to head
void goodInsert(Node **head, int data) {
Node *newNode = createNode(data);
newNode->next = *head;
*head = newNode;
}
9. Linked List Algorithms Summary
| Algorithm | Description | Time Complexity |
|---|---|---|
| Traversal | Visit all nodes | O(n) |
| Search | Find element | O(n) |
| Insert at head | Add at beginning | O(1) |
| Insert at tail | Add at end | O(n) |
| Insert at position | Add at index | O(n) |
| Delete at head | Remove first | O(1) |
| Delete at tail | Remove last | O(n) |
| Delete by value | Remove matching | O(n) |
| Reverse | Reverse order | O(n) |
| Detect cycle | Floyd's algorithm | O(n) |
| Find middle | Tortoise and hare | O(n) |
| Merge sorted lists | Combine two sorted | O(n+m) |
| Remove duplicates | Delete repeated | O(n) or O(nÂČ) |
10. Best Practices
- Always check malloc return - Handle allocation failures
- Maintain head pointer - Never lose reference to list start
- Use temporary pointers - When modifying links
- Free memory properly - No memory leaks
- Validate parameters - Check for NULL inputs
- Document ownership - Who frees the memory
- Consider edge cases - Empty list, single element
- Use const when appropriate - For read-only parameters
- Implement debug functions - Print list for testing
- Write unit tests - Verify all operations
Conclusion
Linked lists are fundamental data structures that every C programmer must master. They demonstrate key concepts:
- Dynamic memory allocation - Creating nodes at runtime
- Pointer manipulation - The essence of C programming
- Algorithm implementation - Various operations and their complexity
- Memory management - Proper allocation and deallocation
- Data structure design - Trade-offs between different implementations
Key takeaways:
- Singly linked lists are simple but limited to forward traversal
- Doubly linked lists enable bidirectional traversal
- Circular lists are useful for round-robin applications
- Generic lists can store any data type
- Always handle edge cases and memory properly
Mastering linked lists provides the foundation for understanding more complex data structures and is essential for system programming, embedded systems, and algorithm design.
Complete C Programming Guide + Compilers Collection
1. C srand() Function â Understanding Seed Initialization
https://macronepal.com/understanding-the-c-srand-function
Explains how srand() initializes the pseudo-random number generator in C by setting a seed value. Using the same seed produces the same sequence, while time(NULL) gives different results each run.
2. C rand() Function Mechanics and Limitations
https://macronepal.com/c-rand-function-mechanics-and-limitations
Explains how rand() generates pseudo-random numbers between 0 and RAND_MAX, its deterministic nature, and limitations for security use cases.
3. C log() Function
https://macronepal.com/c-log-function-2
Covers natural logarithm calculation using <math.h> and its applications.
4. Mastering Date and Time in C
https://macronepal.com/mastering-date-and-time-in-c
Explains <time.h> functions like time(), clock(), difftime(), and struct tm.
5. Mastering time_t Type in C
https://macronepal.com/mastering-the-c-time_t-type-for-time-management
Explains time representation as seconds since Unix epoch and conversion functions.
6. C exp() Function
https://macronepal.com/c-exp-function-mechanics-and-implementation
Explains exponential function exp(x) and its scientific applications.
7. C log() Function (Alternate Guide)
https://macronepal.com/c-log-function
Comparison of log() and log10() with usage examples.
8. C log10() Function
https://macronepal.com/mastering-the-log10-function-in-c
Explains base-10 logarithm for engineering and scientific applications.
9. C tan() Function
https://macronepal.com/understanding-the-c-tan-function
Explains tangent function and radian-based calculations.
10. Random Numbers in C (Secure vs Predictable)
https://macronepal.com/mastering-c-random-numbers-for-secure-and-predictable-applications
Explains difference between rand() and secure randomness methods.
11. Free Online C Compiler
https://macronepal.com/free-online-c-code-compiler-2
Browser-based compiler for testing C programs instantly.
C Functions, Arguments, Parameters & Flow
Mastering Functions in C â Complete Guide
https://macronepal.com/c/mastering-functions-in-c-a-complete-guide/
Covers function structure, modular programming, and real-world usage.
Function Arguments in C
https://macronepal.com/c-function-arguments/
Explains how arguments are passed and used in function calls.
Function Parameters in C
https://macronepal.com/c-function-parameters/
Explains defining inputs for functions and matching them with arguments.
Function Declarations in C
https://macronepal.com/c-function-declarations-syntax-rules-and-best-practices/
Covers prototypes, syntax rules, and best practices.
Function Calls in C
https://macronepal.com/understanding-function-calls-in-c-syntax-mechanics-and-best-practices/
Explains execution flow and parameter handling during function calls.
Void Functions in C
https://macronepal.com/understanding-void-functions-in-c-syntax-patterns-and-best-practices/
Explains functions that do not return values.
Return Values in C
https://macronepal.com/c-return-values-mechanics-types-and-best-practices/
Explains different return types and how functions return results.
Pass-by-Value in C
https://macronepal.com/aws/understanding-pass-by-value-in-c-mechanics-implications-and-best-practices/
Explains how copies of variables are passed into functions.
Pass-by-Reference in C
https://macronepal.com/c/understanding-pass-by-reference-in-c-pointers-semantics-and-safe-practices/
Explains using pointers to modify original variables.
C strstr() Function
https://macronepal.com/aws/c-strstr-function/
Explains substring search inside strings in C.
C Preprocessor & Macros
https://macronepal.com/mastering-c-variadic-macros-for-flexible-debugging/
https://macronepal.com/mastering-the-stdc-macro-in-c/
https://macronepal.com/c-time-macro-mechanics-and-usage/
https://macronepal.com/understanding-the-c-date-macro/
https://macronepal.com/c-file-type/
https://macronepal.com/mastering-c-line-macro-for-debugging-and-diagnostics/
https://macronepal.com/mastering-predefined-macros-in-c/
https://macronepal.com/c-error-directive-mechanics-and-usage/
https://macronepal.com/understanding-the-c-pragma-directive/
https://macronepal.com/c-include-directive/
C Structures, Memory, Scope & Linkage
https://macronepal.com/mastering-structures-in-c/
https://macronepal.com/c-structure-declaration-mechanics-and-usage/
https://macronepal.com/c-structure-initialization-mechanics-and-best-practices/
https://macronepal.com/mastering-c-structure-member-access-for-reliable-data-handling/
https://macronepal.com/c-nested-structures/
https://macronepal.com/mastering-arrays-of-structures-in-c/
https://macronepal.com/c-structure-pointers-mechanics-and-implementation/
https://macronepal.com/understanding-c-structure-parameter-passing-mechanics/
https://macronepal.com/mastering-c-returning-structures-for-efficient-data-flow/
https://macronepal.com/c-self-referential-structures/
https://macronepal.com/mastering-structure-alignment-in-c/
https://macronepal.com/c-structure-padding-mechanics-and-optimization/
https://macronepal.com/understanding-c-flexible-array-members-mechanics-and-usage/
https://macronepal.com/mastering-c-anonymous-structures-for-flattened-data-layouts/
https://macronepal.com/c-unions/
https://macronepal.com/mastering-c-name-mangling-and-symbol-decoration/
https://macronepal.com/c-no-linkage-mechanics-and-scope-isolation/
https://macronepal.com/understanding-c-internal-linkage-mechanics-and-architecture/
C Scope, Storage Classes & Typedef
https://macronepal.com/mastering-function-prototype-scope-in-c/
https://macronepal.com/c-function-scope-mechanics-and-visibility/
https://macronepal.com/understanding-c-file-scope-mechanics-and-architecture/
https://macronepal.com/mastering-c-scope-rules-for-predictable-name-resolution/
https://macronepal.com/c-scope-rules/
https://macronepal.com/mastering-c-register-storage-class-for-historical-context-and-modern-alternatives/
https://macronepal.com/mastering-_thread_local-in-c/
https://macronepal.com/c-extern-storage-class-mechanics-and-usage/
https://macronepal.com/understanding-the-c-static-storage-class-mechanics-and-usage/
https://macronepal.com/c-auto-storage-class/
https://macronepal.com/c-typedef-with-pointers/
Extra Articles
https://macronepal.com/13757-2/
https://macronepal.com/13748-2/
https://macronepal.com/13747-2/
https://macronepal.com/13746-2/
https://macronepal.com/13745-2/
https://macronepal.com/13708-2/
https://macronepal.com/13707-2/
https://macronepal.com/13702-2/
Online Compilers
https://macronepal.com/free-html-online-code-compiler/
https://macronepal.com/free-online-python-code-compiler/
https://macronepal.com/free-online-python2-code-compiler/
https://macronepal.com/free-online-java-code-compiler/
https://macronepal.com/free-online-javascript-code-compiler/
https://macronepal.com/free-online-node-js-code-compiler/
https://macronepal.com/free-online-c-code-compiler/
https://macronepal.com/free-online-c-code-compiler-2/
https://macronepal.com/free-online-c-code-compiler-3/
https://macronepal.com/free-online-php-code-compiler/
https://macronepal.com/free-online-ruby-code-compiler/
https://macronepal.com/free-online-perl-code-compiler/
https://macronepal.com/free-online-lua-code-compiler/
https://macronepal.com/free-online-tcl-code-compiler/
https://macronepal.com/free-online-groovy-code-compiler/
https://macronepal.com/free-online-j-shell-code-compiler/
https://macronepal.com/free-online-haskell-code-compiler/
https://macronepal.com/free-online-scala-code-compiler/
https://macronepal.com/free-online-common-lisp-code-compiler/
https://macronepal.com/free-online-d-code-compiler/
https://macronepal.com/free-online-ada-code-compiler/
https://macronepal.com/free-erlang-code-compiler/
https://macronepal.com/free-online-assembly-code-compiler/
