Functionality of DMA in C Programming

Introduction

Though Array can be used for data storage, they are of fixed size. The programmer must know the size of the array or data while writing the programs. In most situations, it is not possible to know the size of memory required until runtime. Thus, the significance of pointers becomes clear in these situations when dynamic memory allocation is required.

At execution time, a program can request more memory from a free memory pool (heap). Dynamic allocation refers to the allocation of such mammary duty program execution. The only way to access this dynamically allocated memory is through pointers.

To understand the stack and heap, let us examine the organization of memory with respect to the following program.

#include <stdio.h>
int g = 50;

void func(int p) {
    static int s = 200;
    int i = 10;
    printf("%d%d\n", i, s);
}

void main() {
    int a = 1;
    printf("%d\n", a);
    printf("%d\n", g);
    func(-16);
    printf("over!\n");
}

Output

Output

This program has a global integer g and two functions func and main. The function func has a local variable i and a local static variable s. The function main has a local variable a.

The function func

All local variables and parameters are placed on the stack. Hence, p is on the stack, since a and i are local variables, they are placed on the stack. When execution is inside the main, only the variable a would exist on the stack. When the function func is called, the value of the parameter passed, which is -16, is passed on the stack. Then, the return address in the main is pushed, and the control transferred to func. The variable i is then created on the stack. If func accesses the variable p and i it will be accessing their location on the stack. When func returns, the variable i is removed from the stack. The stack pointer then points to the return address on the stack. The control returns to this address on the parameter p is removed from the stack. The free memory space, called a heap, is available for dynamic memory allocation. The program can allocate and free memory from this area using certain standard library functions of which malloc and free are the important ones.

Library function for Dynamic Memory Allocation

There are many built-in standard library functions for efficient dynamic memory allocation/de-allocation. Their prototypes are declared in alloc. h and stdlib.h. The function are: calloc(), free(), malloc() and realloc().

void *malloc(size_t size);

The function malloc allocates a block of size bytes from the free data area (heap). It allows a program to allocate an exact amount of memory explicitly, as and when needed. The parameter passed to malloc is of type size_t. This type is declared in the reader file stdlib.h size_tnis equivalent to the undersigned int data types. Thus, in compilers where int is 16 bits in size, malloc can allocate a maximum of 64 KB at a time, since the maximum value of an unsigned int is 65535.

Return Value

On success, malloc returns a pointer to the newly allocated block of memory. On error, malloc returns NULL. The constant NULL is defined in stdio.h to have a value of zero.

int *buf;
buf = (int *)malloc(200 * sizeof(int));

if (buf == NULL) {
    printf("Not enough memory, Shikha Tiwari");
}

if (buf == NULL) {
    printf("Not enough memory!");
}

free()

void free (void*block);

free de-allocates a memory block allocated previously by calloc,malloc or realloc.

Write a program using malloc and free.

#include <stdio.h>
#include <stdlib.h>
void main() {
    int n, i, *ary;

    clrscr(); // Note: clrscr() is not standard and may not work in all environments
    printf("\nHow many elements, Shikha? : ");
    scanf("%i", &n);
    printf("%i\n", n);

    // Allocate memory for the array
    if (!(ary = (int *)malloc(n * sizeof(int)))) {
        // Check if memory allocation was successful
        printf("No memory for the array");
        exit(1);
    }

    printf("Enter the elements : \n");
    for (i = 0; i < n; i++) {
        scanf("%i", ary + i);
    }

    printf("\nThe entered array is : \n");
    for (i = 0; i < n; i++) {
        printf("%i\n", ary[i]);
    }

    // Free allocated memory
    free(ary);

    getch(); // Note: getch() is not standard and may not work in all environments
}

Output

Output2

calloc()

void*calloc(size_t nitems, size_t size);

Calloc provides access to the C memory heap, which is available for dynamic allocation of variable-sized blocks of memory. Unlike malloc, the function calloac accepts two arguments: items and size.

The parameters nitems specify the number of items to allocate and size specifies the size of each item.

For example, to allocate 10 integers, the following statements

ary=(int*)calloc(n,sizeof(int));

The function calloc allocates a block of size (nitems*size).

One important difference between malloc and calloc is that calloc initializes all bytes in the allocated block to zero.

On success, calloc returns a pointer to the newly allocated blocks. On failure, calloac returns NULL. These functions return void pointers.

realloc()

void *realloc(void*block,size_t size);

realloc adjusts the amount of memory allocated to the block to size, copying the content to a new location if necessary.

Write a program to illustrate the uses of realloc() anf free() functions.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main() {
    char *testname;

    clrscr(); // Note: clrscr() is not standard and may not work in all environments

    // Allocate memory for 26 characters
    if ((testname = (char *)malloc(26)) == NULL) {
        printf("Could not allocate memory to store 26 characters");
        exit(1);
    }

    strcpy(testname, "SHIKHA tiwari");
    printf("\nThe value contained in testname is %s\n", testname);

    // Reallocate memory for 48 characters
    testname = realloc(testname, 48);
    if (testname == NULL) {
        printf("Could not reallocate memory to store 48 characters");
        exit(1);
    }
    printf("testname contains %s after reallocation of memory\n", testname);

    strcpy(testname, "SHIKHA tiwari");
    printf("testname contains %s after reallocating memory and copying new string\n", testname);

    // Reallocate memory to store a smaller string
    testname = realloc(testname, 13);
    if (testname == NULL) {
        printf("Could not reallocate memory to store smaller size");
        exit(1);
    }
    strcpy(testname, "ghaziabad");
    printf("testname contains %s after reallocating memory to smaller size and copying new string\n", testname);

    // Free allocated memory
    free(testname);

    getch(); // Note: getch() is not standard and may not work in all environments
}

Output

Output3

The given C program demonstrates dynamic memory allocation and manipulation of a string using the `malloc` and `realloc` functions. It starts by declaring a character pointer `testname` and attempts to allocate 26 bytes of memory to it. If the allocation fails, an error message is displayed and the program exits. If successful, the string "SHIKHA Tiwari" is copied into the allocated memory, and its content is printed. The program then attempts to reallocate the memory to 48 bytes and checks for successful reallocation, printing the current string again. Subsequently, it reallocates the memory to a smaller size of 13 bytes and copies a new string "Ghaziabad" into it, printing the updated content. Finally, the allocated memory is freed. The `clrscr` and `getch` functions are used for screen clearing and pausing the program, respectively, though they are specific to certain environments and not part of the standard C library.

Summary

The program provides a practical demonstration of dynamic memory allocation in C using `malloc` and `realloc`. Initially, it allocates memory for 26 characters to store the string "SHIKHA Tiwari" and checks for successful allocation, displaying an error message and exiting if allocation fails. It then reallocates the memory to 48 bytes to accommodate potential larger strings, verifying the success of reallocation and retaining the original string content. Next, it resizes the allocated memory to 13 bytes and updates the stored string to "Ghaziabad". Throughout the process, the program ensures memory is properly managed and concludes by freeing the allocated memory to prevent leaks. This highlights the flexibility and necessity of dynamic memory management in handling varying data sizes efficiently.


Similar Articles