Understanding Dynamic Memory Allocation in C with Pointers

Understanding Dynamic Memory Allocation in C with Pointers

Pointers and Dynamic Memory Allocation

In C programming, arrays have fixed sizes because variables (including integers, floats, characters, and arrays) are stored in the stack space, whose size is determined at compile time. When memory requirements are unknown at compile time, heap space must be used instead.

Example 1: Dynamic Memory Allocation


#include <stdio.h>
#include <stdlib.h> // Header file for malloc
#include <string.h>

int main(int argc, const char * argv[]) {
    int capacity; // Represents the number of bytes to allocate
    char *buffer; // We can't use void* for pointer arithmetic
    
    scanf("%d", &capacity);
    
    // malloc returns a void* pointer representing untyped memory
    buffer = (char *)malloc(capacity); // Allocate space on the heap
    strcpy(buffer, "Allocation successful");
    puts(buffer);
    
    free(buffer); // Must use the exact pointer returned by malloc
    printf("Memory freed successfully\n");
    
    return 0;
}
</string.h></stdlib.h></stdio.h>

Let's examine the malloc function. When including <stdlib.h>, the function is declared as void *malloc(size_t size). The parameter size_t is essentially an integer type, and malloc returns a void* pointer. A void* pointer can only store an address but cannot be used for pointer arithmetic because malloc doesn't know what type of data will be stored in the allocated space. Therefore, after determining the data type, we must cast the void* pointer to the appropriate type. In this example, we're storing characters, so we cast it to char*.

Important: The size of the pointer itself and the size of the memory it points to are two different concepts and shouldn't be confused with regular variables!

Differences Between Stack and Heap Memory

Consider the following: integer variables and pointers declared within a function reside in that function's stack space. When memory is allocated with malloc, it returns the address of the first byte in the heap space. This address is stored in our pointer variable. Once we have this address, we can use functions like strcpy to store character data in the allocated space.

Stack and Heap Memory Comparison

Since both are memory spaces, why do we need separate stack and heap areas?

  1. The stack is a data structure provided by the computer system. The system provides low-level support for stacks, including dedicated registers to store stack addresses and special instructions for push and pop operations, making stacks more efficient.
  2. The heap is a data structure provided by C/C++ libraries with a complex mechanism. For example, to allocate memory, library functions search the heap for a sufficiently large block using specific algorithms. If no suitable block is available (possibly due to memory fragmentation), the system might need to resize the program's data segmant, which is less efficient.

Heap operations are significantly less efficient than stack operations!

Stack memory is automatically managed by the system, while heap memory must be manually managed. In the examples, we use the free function to release heap memory. The free functon is declared as:


#include <stdlib.h>
void free(void *ptr);
</stdlib.h>

The parameter is of type void*, so any pointer can be automatically converted to void* when passed to free. When passing a pointer to free, no type casting is needed. The address value passed to free must be exactly the address returned by malloc; any modification to this pointer (like p = p + 1) between allocation and deallocation will cause problems. This is because when allocating heap memory, the kernel records only the starting address and size. During deallocation, the kernel uses this starting address to match the block. If the addresses don't match, the program will crash. If you need to offset the pointer or store data, define a separate pointer variable to maintain the original address for proper deallocation.

Example 2: Demonstrating Stack and Heap Differences


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

// Stack memory is automatically released when the function ends
char *demonstrate_stack() {
    char message[17] = "I'm in the stack";
    puts(message);
    return message; // Returning pointer to stack memory
}

// Heap memory persists after the function ends
char *demonstrate_heap() {
    char *heap_memory;
    heap_memory = (char *)malloc(20);
    strcpy(heap_memory, "I'm in the heap");
    puts(heap_memory);
    return heap_memory; // Returning pointer to heap memory
}

int main(int argc, const char * argv[]) {
    char *result;
    
    result = demonstrate_stack(); // Data in stack space
    printf("Stack result: %s\n", result); // This may print garbage
    
    result = demonstrate_heap(); // Data in heap space
    printf("Heap result: %s\n", result); // This will print correctly
    
    free(result); // Only the heap memory needs to be freed
    
    return 0;
}
</string.h></stdlib.h></stdio.h>

Tags: c programming Memory Management dynamic allocation pointers malloc

Posted on Fri, 09 Oct 2026 16:43:49 +0000 by lunac