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), sizeof automatically 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: *ptr when ptr == NULL can 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); write ptr = 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() return void * 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