C Programming - Beginner to Brilliance / Pointers in C

Dynamic Memory Allocation

๐Ÿช„ What is Dynamic Memory Allocation?

Dynamic memory allocation means allocating memory during program execution (runtime) instead of compile-time.

Unlike static memory (like arrays), where you must know the size ahead of time, dynamic memory lets you request memory when needed โ€” and free it later.


๐ŸŽฏ Why Use Dynamic Memory Allocation?

Static Memory (int arr[100];)

Dynamic Memory (malloc)

Fixed size at compile-time

Flexible size at runtime

May waste memory

Efficient usage

Stack allocation

Heap allocation

Limited size

Much larger space


๐Ÿงฐ Functions Used (All from <stdlib.h>)

Function

Description

malloc()

Allocates memory block

calloc()

Allocates and initializes memory

realloc()

Resizes previously allocated memory

free()

Frees previously allocated memory


๐Ÿ“ฆ malloc() โ€“ Memory Allocation

๐Ÿ“Œ Purpose:

Allocates a specified number of bytes in memory and returns a void pointer to the first byte of the allocated space.

๐Ÿ’ก Characteristics:

  • Memory is uninitialized (contains garbage values).

  • Returns NULL if memory allocation fails.

๐Ÿงช Syntax:

ptr = (cast_type *) malloc(size_in_bytes);

โœ… Example:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *ptr = (int *)malloc(sizeof(int) * 5);
    
    // Checking if failed or pass
    if (ptr == NULL) {
        printf("Allocation Failed");
        exit(0);
    }
    
    // Populate the array
    for (int i = 0; i < 5; i++)
        ptr[i] = i + 1;
        
    // Print the array
    for (int i = 0; i < 5; i++)
        printf("%d ", ptr[i]);
    return 0;
}

๐Ÿ“ sizeof(int) is used to calculate size in bytes, ensures portability.

โš ๏ธ Important:

  • Always check if the returned pointer is NULL.

  • Cast is optional in C but required in C++.


๐Ÿ“ฆ calloc() โ€“ Contiguous Allocation

๐Ÿ“Œ Purpose:

Allocates memory for an array of elements and initializes all bytes to zero.

๐Ÿ’ก Characteristics:

  • Useful when you want a clean memory block.

  • Slower than malloc() because of the initialization step.

๐Ÿงช Syntax:

ptr = (cast_type *) calloc(num_elements, size_of_each);

โœ… Example:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *ptr = (int *)calloc(5, sizeof(int));
    
    // Checking if failed or pass
    if (ptr == NULL) {
        printf("Allocation Failed");
        exit(0);
    }
    
    // No need to populate as already
    // initialized to 0
        
    // Print the array
    for (int i = 0; i < 5; i++)
        printf("%d ", ptr[i]);
    return 0;
}

๐Ÿ”„ realloc() โ€“ Reallocation of Memory

๐Ÿ“Œ Purpose:

Changes the size of a previously allocated memory block (malloc or calloc) without losing existing data (if possible).

๐Ÿ’ก Characteristics:

  • Expands or shrinks the memory block.

  • May move memory to a new location.

  • If it fails, it returns NULL without freeing the original block.

๐Ÿงช Syntax:

ptr = realloc(ptr, new_size);

โœ… Example:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *ptr = (int *)malloc(5 * sizeof(int));

    // Resize the memory block to hold 10 integers
    ptr = (int *)realloc(ptr, 10 * sizeof(int));
    
    // Check for allocation failure
    if (ptr == NULL) {
        printf("Memory Reallocation Failed");
        exit(0);
    }

    return 0;
}

โŒ free() โ€“ Free Allocated Memory

๐Ÿ“Œ Purpose:

Releases dynamically allocated memory back to the system.

๐Ÿ’ก Characteristics:

  • Helps prevent memory leaks.

  • Once freed, accessing the pointer is undefined behavior.

๐Ÿงช Syntax:

free(ptr);

โœ… Example:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *ptr = (int *)calloc(sizeof(int), 5);
    
    // Do some operations.....
    for (int i = 0; i < 5; i++)
        printf("%d ", ptr[i]);
        
    // Free the memory after completing
    // operations
    free(ptr);
    
    return 0;
}

After calling free(ptr), the pointer ptr becomes a dangling pointer unless set to NULL.


๐Ÿ’ก Memory Layout in C (Stack vs Heap)

  • Static memory (like int arr[10]) goes on stack

  • Dynamic memory (like malloc) is allocated on heap


โš ๏ธ Common Mistakes in DMA

Mistake

Why itโ€™s bad

Forgetting free()

Leads to memory leak

Using memory after free()

Undefined behavior (dangling pointer)

Not checking malloc() return value

Can crash on NULL

Incorrect size calculation

May lead to buffer overflows


๐Ÿ” Best Practices

โœ… Always check if allocation was successful

โœ… Use sizeof instead of hardcoding

โœ… Always free() when done

โœ… Set pointer to NULL after freeing

โœ… Avoid memory leaks by keeping track of all allocations


๐Ÿš€ Real-Life Applications

  • ๐ŸŒฒ Dynamic Data Structures: Linked Lists, Trees, Graphs

  • ๐Ÿ“ฆ Memory-efficient storage in large programs

  • ๐ŸŽฎ Game development and resource loading

  • ๐Ÿ’พ Operating systems and embedded systems