Dynamic Memory Allocation

The process of allocating memory during program execution is called Dynamic Memory Allocation.

The exact size of an array is unknown until the compile time. The size of array that you have declared initially can be sometimes insufficient and sometimes more than required. Dynamic Memory Allocation allows a program to obtain more memory space, while running or to release space when no space is required.

Dynamic Memory Allocation in c language is possible by 4 functions of stdlib.h header file.

  • malloc()
  • calloc()
  • realloc()

Above three functions Allocates a block of memory on the heap

  • free()

free() Deallocates a block of memory on the heap

In order to use these 4 functions, header file <stdlib.h> has to be added.

 

E.g.

 #include<stdlib.h>

Difference between Static and Dynamic memory allocation

In Dynamic Memory Allocation, memory is allocated at run time. Whereas in Static Memory Allocation, memory is allocated at compile time.

Example :

//Static allocation:
int a[20];

//Dynamic allocation
int *ptr;
ptr=(int *)malloc(sizeof(int)*20);

Malloc

The name malloc stands for “memory allocation”. The function malloc() reserves a block of memory of specified size and return a pointer of type void which can be casted into pointer of any form.

Syntax :

void * malloc (size_t size);

size_t : stores only positive integer value, you can think of this particular datatype as unsigned integer datatype.
size cannot be negative , it can be either positive or zero value.
Malloc return a void pointer that gives us the address of the first byte in the block of memory that it allocates.

Example :

void *malloc(2*sizeof(int)); //(no of elements * size of one unit)

this will store 2 * 4 = 8 byte on the memory say from address 201 to 208, ie. It allocates a block of memory for array of 2 integer , each of 4 byte

Value1 Value2
201 205

so the malloc will return void ptr to the address of the first byte i.e 201.

if we want to store values at these addresses.

  • As malloc return void ptr, and void ptr cannot be de-referenced, so we cannot directly assign the values as *p = 2;
  • void ptr can be typecasted into a pointer type of particular datatype and then it is used.
  • Inorder to use this block of memory we first need to typecast this void pointer of some datatype like this

Syntax :

    datatype *ptr=(cast-type*)malloc(byte-size)
    pointer = (type) malloc (size in bytes);

Example :

ptr=(int*)malloc(2*sizeof(int));//2*4=8bytes

By asking memory block of 2 integers, we are basically creating an array of integers with 2 elements.

 

Assigning values to the address :

ptr = 2; // this will assign value at the address say 201

(ptr + 1) = 3; // this will assign value at the address 205

Getting the address

&ptr[0] to get the address of first element and &ptr[1] to get the address of second element.

To access the values stored at the addresses

*ptr will give the value as 2
*(ptr + 1) will give the value 3

We can use ptr[0] to get the value 2 and ptr[1] to get the value 3.

To get next element in the array, you can increment the pointer.

Example :

#include <stdio.h>
    #include <stdlib.h>
    void main()
    {
    int n,i,*ptr,sum=0;

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

    ptr=(int*)malloc(n*sizeof(int)); //memory allocated using malloc

    if(ptr==NULL)
    {
    printf("Requested size of memory is unavailable ");
    exit(0);
    }

    printf("Enter elements of array: ");
    for(i=0;i<n;++i)
    {
    scanf("%d",ptr+i);
    sum+=*(ptr+i);
    }
    printf("Sum=%d",sum);
    }

 


Output :

Enter number of elements: 4
Enter elements of array:
5
5
5
5
Sum=20

 

Calloc

The name calloc stands for “contiguous allocation”.
The only difference between malloc() and calloc() is that, malloc() allocates single block of memory whereas calloc() allocates multiple blocks of memory each of same size and sets all bytes to zero.
Another difference between malloc and calloc is that , malloc allocates some amount of memory , it does not initialize the byte with any value, so if you do not fill any values in the addresses allocated by malloc,the malloc will assign garbage values in the block of memory,
but if the memory is allocated by calloc, the calloc sets all byte position to value zero, so it initializes the memory that it allocates to zero.
Calloc also returns a void pointer same as malloc.

 

Syntax :

void * calloc (size_t n, size_t size);

there are two arguments,

1. size_t n : the number of elements of particular datatype
2. size_t size : the size of the datatype.

 

Example :

ptr=(cast-type*)calloc(n,element-size);

This statement will allocate contiguous space in memory for an array of n elements

ptr=(float*)calloc(25,sizeof(float));

This statement allocates contiguous space in memory for an array of 25 elements each of size of float, i.e, 4 bytes.

Example :

    #include <stdio.h>
    #include <stdlib.h>
    void main()
    {
    int n,i,*ptr,sum=0;

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

    ptr=(int*)calloc(n,sizeof(int)); //memory allocated using calloc

    if(ptr==NULL)
    {
    printf("Requested size of memory is unavailable ");
    exit(0);
    }

    printf("Enter elements of array: ");
    for(i=0;i<n;++i)
    {
    scanf("%d",ptr+i);
    sum+=*(ptr+i);
    }
    printf("Sum=%d",sum);
    }

Output :

Enter number of elements: 4
Enter elements of array:
5
5
5
5
Sum=20

Realloc

relloc() function is used to change the size of a dynamically allocated block of memory.

If memory is not sufficient for malloc() or calloc(), you can reallocate the memory by realloc() function.

Syntax :

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

void ptr : is the pointer to the starting address of the existing block

size : size of the new block

 

Tips :

int *a = (int*)realloc(a,0); //this is equivalent to free() as this will deallocate the complete block of a.
int *a=(int *)realloc(NULL,n*sizeof(int)); //this is equivalent to malloc(). This only creates new block of memory of size n.

Note :

  • If the size of the new block is larger then the size of the previous block then the machine will create entirely new block and copy the previous data written in the previous block of memory to the new block of memory.
  • If the contiguous block of memory is available with the existing block, then the existing block will be extended.

Free

Any dynamically located memory, remains allocated till the time that program is available. To deallocate the memory we need to explicitly deallocate the memory by using function free()

Example malloc,realloc,free :

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

    void main()
    {
    int n;

    printf(“Enter size of array”);
    scanf(“%d”, &n);

    int *a = (int)malloc(n*sizeOf(int)); //dynamically allocated array
    //if we donot initialize the values in the array, then by default the malloc will assign garbage values in the block
    of memory
    //so if we comment the below for loop then it will print garbage values

    for(int i = 0; i < n; i++)
    {
    a[i]=i+1;//assigning values as 1,2,3..n;
    }

    //if we use free() function below, to free the memory space then free() function will erase all the data from
    memory.

    //Free(a);// so better not to use free() here

    //now this below for loop will print garbage values because the free() has removed all data from memory.
    //To resize the memory block: we have memory block to store n elements in an array, and we want to double the size
    of array or want to reduce the size, so for this we can use realloc().

    int *b = (int )realloc(a,2*n*sizeof(int));//this will allocate double the size of previous block.
    //after realloc(), it will create new memory block of size 2n and copy the values of previous block of memory values
    into the new memory block b.
    //so previous values for n =2,were a[0]=1 and a[1]=2, then after realloc, the block of memory will be 2*n=2*2=4
    //so if we print the values that is there in the new block b as


    for(int i = 0; i < n; i++)
    {
    printf(“%d ”,b[i]);
    //n=2,so new size of memory block is 2*2=4,this will print values as “1 2 garbagevalue1 garbagevalue2”.
    //since 1 and 2 are values of previous block a, so they are copied in the new block b
    //and garbage values are printed in the new block of memory because till now no values are assigned in the new block
    of memory
    }


    for(int i = 0; i < n; i++)
    {
    printf(“%d ”,a[i]); //this will print values as 1 2 3...n
    }
    //this will deallocate after the block of memory has been used , so that it can be reused.
    free();
    }

Example for calloc():

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

    void main()
    {
    int n;

    printf(“enter size of array”);
    scanf(“%d”, &n);

    int *a = (int)calloc(n*sizeOf(int)); //dynamically allocated array
    //if we do not initialize the values in the array then by default the calloc will assign zeros in the block of
    memory.
    //so if we comment the below for loop then it will print all values as zero on the console
    //and if we assign values by using the below for loop , then it print all the values that are assigned in the block
    of memory
    for(int i = 0; i < n; i++)
    {
    a[i]=i+1;//assigning values as 1,2,3...n;
    }

    for(int i = 0; i < n; i++)
    {
    printf(“%d ”,a[i]); //this will print values as 1 2 3...n
    }
    }