Creating a Node (Dynamic Memory Allocation)
In linked lists, every node is usually created at runtime on the heap. This is called dynamic memory allocation: memory is requested when needed and released with free() when the node is deleted.
1) How dynamic memory is allotted to a node
struct Node {
int data;
struct Node *next;
};
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
if (newNode == NULL) {
// allocation failed
}
newNode->data = 25;
newNode->next = NULL;
malloc()reserves memory from the heap.- The returned address is stored in a pointer (
newNode). - Then fields are initialized and the node is linked into the list.
2) Allot memory using malloc() and calloc()
// malloc: allocates one block, contents are uninitialized
struct Node *a = (struct Node *)malloc(sizeof(struct Node));
// calloc: allocates n blocks and initializes all bytes to zero
struct Node *b = (struct Node *)calloc(1, sizeof(struct Node));
malloc(size): gives raw memory; old data may remain in bytes.calloc(n, size): gives zero-initialized memory (useful default state).- For linked-list nodes, both are valid; just remember to assign required fields explicitly.
3) Why sizeof is important here
sizeof(struct Node)allocates the exact number of bytes needed for one node.- It prevents hard-coded sizes (like
malloc(16)) that break across systems/compilers. - If the structure changes (new fields added),
sizeofautomatically adjusts. - A common safe form is
malloc(sizeof(*newNode)), tied directly to pointer type.
4) Why type casting is required (or not) while allocating
In C, malloc() returns a void *, which is automatically converted to any object pointer type. So cast is optional in pure C, but often written in beginner examples for clarity.
// Valid in C (recommended by many C style guides)
struct Node *p = malloc(sizeof(struct Node));
// Also valid in C (explicit cast)
struct Node *q = (struct Node *)malloc(sizeof(struct Node));
- In C++, cast is required because implicit conversion from
void *is not allowed. - In C, unnecessary casting can hide missing header issues (
<stdlib.h>), so be careful.
5) What is NULL? What is a NULL pointer?
NULL is a macro used to represent a pointer that points to nothing (no valid object/function).
It is typically defined in standard headers like <stdio.h>, <stdlib.h>, and <stddef.h> as:
#define NULL ((void *)0)
// or sometimes
#define NULL 0
A NULL pointer is any pointer variable whose value is NULL. Conceptually this means pointer value zero in C; the runtime treats it as “points nowhere.”
6) Common uses of NULL
// 1) Initializing pointers safely
int *ptr = NULL;
// 2) "Not pointing to anything yet"
char *name = NULL;
name = malloc(100);
if (name == NULL) {
printf("Memory allocation failed\n");
}
// 3) Validate before dereference
int *data = getData(); // may return NULL
if (data != NULL) {
printf("%d\n", *data);
}
// 4) Linked list termination
struct Node {
int value;
struct Node *next;
};
struct Node *head = NULL; // empty list
// last node has next == NULL
// 5) Error return checks
FILE *file = fopen("config.txt", "r");
if (file == NULL) {
printf("File not found\n");
}
7) Why do malloc() / calloc() return NULL?
- Insufficient heap memory: allocator cannot provide requested bytes.
- Too large request: requested size exceeds available/allowed limits.
- Memory pressure / fragmentation / limits: runtime or OS rejects allocation.
struct Node *newNode = malloc(sizeof(struct Node));
if (newNode == NULL) {
// handle allocation failure safely
return;
}
8) Important rules and best practices
- Never dereference NULL:
*ptrwhenptr == NULLcan crash (segmentation fault). - Always check for NULL: especially after
malloc(),calloc(),fopen(), etc. - Initialize pointers to NULL: avoids garbage addresses and undefined behavior.
- Set freed pointers to NULL: after
free(ptr);writeptr = NULL;to reduce dangling pointer misuse.
9) NULL vs '\0' vs 0
| Symbol | Type | Purpose |
|---|---|---|
NULL |
Pointer constant | Indicates a pointer points nowhere |
'\0' |
Character constant | Null character, used as C-string terminator |
0 |
Integer constant | Numeric zero value |
char *ptr = NULL; // pointer to nothing
char ch = '\0'; // null character (ASCII 0)
int x = 0; // integer zero
10) What is a void pointer?
A void pointer (void *) is a generic pointer type that can hold the address of any data type. It does not know the pointed data type by itself.
malloc()/calloc()returnvoid *so they can allocate memory for any type.- You cannot dereference
void *directly because size/type is unknown. - Assign it to a typed pointer (like
struct Node *) before using->fields.
// Simple void pointer example
int x = 42;
float y = 3.14f;
void *vp = &x; // generic pointer stores address of int
int *ip = (int *)vp; // cast to int* before dereference
printf("%d\n", *ip); // 42
vp = &y; // now void pointer stores address of float
float *fp = (float *)vp; // cast to float* before dereference
printf("%.2f\n", *fp); // 3.14