C Program to Dynamically Allocate Memory Using malloc()

C Program to Dynamically Allocate Memory Using malloc()

In C programming, memory can be allocated in two ways: statically and dynamically. Static memory allocation reserves memory at compile time, while dynamic memory allocation allows the program to request memory at runtime. Dynamic allocation is especially useful when the size of the data is not known in advance.

The malloc() function is part of the C standard library and is used to allocate memory dynamically. It allocates a specified number of bytes in the heap and returns a pointer to the first byte of the allocated memory. This tutorial demonstrates how to use malloc() effectively and manage memory safely.

Understanding the Problem

When working with arrays or complex data structures whose sizes are determined at runtime, using static arrays may be insufficient. Dynamic memory allocation with malloc() allows the program to request memory as needed, giving flexibility and efficient memory usage.

For example, reading a user-specified number of integers requires allocating memory dynamically, because the size of the array is not known until runtime.

Program 1: Allocating Memory for an Array Using malloc()

This example shows how to allocate memory dynamically for an array of integers.

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

int main() {

    int n;
    int *arr;

    printf("Enter the number of elements: ");
    scanf("%d", &n);

    // Allocate memory dynamically
    arr = (int *) malloc(n * sizeof(int));

    if (arr == NULL) {
        printf("Memory allocation failed.\n");
        return 1;
    }

    // Input elements
    for (int i = 0; i < n; i++) {
        printf("Enter element %d: ", i + 1);
        scanf("%d", &arr[i]);
    }

    // Print elements
    printf("You entered: ");

    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }

    printf("\n");

    // Free allocated memory
    free(arr);

    return 0;

}

Here, malloc(n * sizeof(int)) requests enough memory to store n integers. Casting to (int *) ensures the returned void * pointer is treated as an integer pointer. After use, free(arr) releases the memory back to the system to prevent memory leaks.

Program 2: Allocating Memory for Structures

Dynamic memory allocation is also useful for structures.

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

struct Student {
    char name[50];
    int age;
};

int main() {

    int n;
    struct Student *students;

    printf("Enter the number of students: ");
    scanf("%d", &n);

    students = (struct Student *) malloc(n * sizeof(struct Student));

    if (students == NULL) {
        printf("Memory allocation failed.\n");
        return 1;
    }

    // Input student data
    for (int i = 0; i < n; i++) {

        printf("Enter name of student %d: ", i + 1);
        scanf("%s", students[i].name);

        printf("Enter age of student %d: ", i + 1);
        scanf("%d", &students[i].age);

    }

    // Print student data
    printf("Student Details:\n");

    for (int i = 0; i < n; i++) {
        printf("Name: %s, Age: %d\n", students[i].name, students[i].age);
    }

    // Free allocated memory
    free(students);

    return 0;

}

In this example, malloc() allocates memory for n structures. Each structure can hold the name and age of a student. Using pointers to structures allows dynamic handling of multiple records without fixed-size arrays.

Program 3: Allocating Memory for a String

Strings can also be created dynamically when the length is not known beforehand. This allows the program to accept flexible input from the user.

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

int main() {

    int length;
    char *str;

    printf("Enter the length of the string: ");
    scanf("%d", &length);

    // Allocate memory for string (plus 1 for null terminator)
    str = (char *) malloc((length + 1) * sizeof(char));

    if (str == NULL) {

        printf("Memory allocation failed.\n");
        return 1;

    }

    printf("Enter a string: ");
    scanf("%s", str);

    printf("You entered: %s\n", str);

    // Free allocated memory
    free(str);

    return 0;

}

Here, the memory size is based on the user’s input plus one extra byte for the null terminator. This way, the string fits exactly into the allocated memory without wasting space.

Program 4: Building a String Dynamically with realloc()

Sometimes you don’t know the length of a string before the user enters it. In such cases, you can allocate memory as needed and resize it dynamically using realloc().

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

int main() {

    char *str = NULL;
    char ch;
    int length = 0;

    printf("Enter a string (press Enter to finish): ");

    while ((ch = getchar()) != '\n' && ch != EOF) {

        // Increase size by 1 each time
        char *temp = realloc(str, (length + 1) * sizeof(char));

        if (temp == NULL) {

            printf("Memory allocation failed.\n");
            free(str);
            return 1;

        }

        str = temp;

        str[length] = ch;
        length++;

    }

    // Add null terminator
    char *temp = realloc(str, (length + 1) * sizeof(char));

    if (temp == NULL) {

        printf("Memory allocation failed.\n");
        free(str);
        return 1;

    }

    str = temp;
    str[length] = '\0';

    printf("You entered: %s\n", str);

    free(str);

    return 0;

}

Here, memory starts as NULL and grows each time a new character is entered. realloc() resizes the memory block safely while keeping old content intact. Finally, the program adds a null terminator and prints the complete string.

Program 5: Using malloc() for a 2D Array

With malloc(), you can even create two-dimensional arrays dynamically. This is useful when both rows and columns are decided at runtime.

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

int main() {

    int rows, cols;
    int **matrix;

    printf("Enter number of rows: ");
    scanf("%d", &rows);
    
    printf("Enter number of columns: ");
    scanf("%d", &cols);

    // Allocate memory for row pointers
    matrix = (int **)malloc(rows * sizeof(int *));

    if (matrix == NULL) {

        printf("Memory allocation failed.\n");
        return 1;

    }

    // Allocate memory for each row
    for (int i = 0; i < rows; i++) {

        matrix[i] = (int *) malloc(cols * sizeof(int));

        if (matrix[i] == NULL) {
            printf("Memory allocation failed.\n");
            return 1;
        }

    }

    // Input elements
    printf("Enter matrix elements:\n");
    for (int i = 0; i < rows; i++) {

        for (int j = 0; j < cols; j++) {
            scanf("%d", &matrix[i][j]);
        }

    }

    // Print matrix
    printf("Matrix:\n");

    for (int i = 0; i < rows; i++) {

        for (int j = 0; j < cols; j++) {
            printf("%d ", matrix[i][j]);
        }

        printf("\n");

    }

    // Free memory
    for (int i = 0; i < rows; i++) {
        free(matrix[i]);
    }

    free(matrix);

    return 0;

}

In this program, memory is allocated first for row pointers, and then for each row separately. Freeing both levels ensures that the memory is completely released back to the system.

FAQs

1. What is malloc() in C?
malloc() is a standard library function in C used to allocate a block of memory dynamically. It reserves the requested number of bytes on the heap and returns a pointer to the beginning of the block. If it fails, it returns NULL.

2. Why do we need dynamic memory allocation?
Dynamic memory allocation is useful when the amount of data is not known at compile time. It lets programs adjust memory usage at runtime, making them more flexible and efficient compared to using only static arrays.

3. What is the difference between malloc() and calloc()?
Both functions allocate memory dynamically, but they behave slightly differently. malloc() allocates uninitialized memory (which may contain garbage values), while calloc() allocates memory and sets all bits to zero, giving predictable results.

4. How do I prevent memory leaks?
To prevent memory leaks, always release memory that was allocated dynamically once it is no longer needed. In C, this is done by calling free() on the allocated pointer, which returns the memory back to the system.

5. What is realloc() and when should I use it?
realloc() is used to change the size of memory that was previously allocated with malloc() or calloc(). It preserves the existing data while resizing the block, making it useful when you need to grow or shrink memory at runtime without losing stored values.

Conclusion

Dynamic memory allocation using malloc() is a powerful feature in C that lets programs manage memory at runtime. With it, you can create arrays, structures, strings, and even 2D arrays whose sizes are determined by user input or other runtime conditions.

By combining malloc(), realloc(), and free(), programmers can write efficient and flexible code that adapts to different data requirements. Mastering these concepts is an important step toward building scalable and reliable C programs.

References & Additional Resources

The following books and online resources provide theoretical foundations and practical guidance on pointers and dynamic memory allocation in C.

  1. Kernighan, B. W., & Ritchie, D. M. (1988). The C Programming Language (2nd Edition). Prentice Hall – Authoritative reference on C fundamentals, including pointers and memory allocation.
  2. Thareja, R. (2011). Data Structures Using C. Oxford University Press – Covers memory management functions, pointers, and their role in data structures.
  3. GeeksforGeeks: malloc() in C – Detailed explanation of malloc(), calloc(), realloc(), and free() with examples.
  4. Tutorialspoint: C Dynamic Memory – Overview of dynamic memory allocation techniques in C.
  5. Cprogramming.com: Pointers in C – Beginner-friendly guide to pointers and their usage in dynamic memory management.
  6. cplusplus.com: malloc() and free() – Reference documentation for memory allocation and deallocation functions.
Scroll to Top