Learn C - C malloc






You can also allocate memory at runtime explicitly.

The simplest standard library function that allocates memory at runtime is called malloc().

When you use the malloc() function, you specify the number of bytes of memory that you want allocated as the argument.

The function returns the address of the first byte of memory that it allocated in response to your request.

A typical example of dynamic memory allocation might be this:

int *pNumber = (int*)malloc(100);

Here, you've requested 100 bytes of memory and assigned the address of this memory block to pNumber.

The following code allocates memory to hold 25 integers.

int *pNumber = (int*)malloc(25*sizeof(int));

(int*) converts the address returned by the function to the type pointer to int.


#include <stdio.h> 
#include <stdlib.h> 
main() //w  w w .  j a v  a2 s  . co  m
{ 
   char *name; 
   name = (char *) malloc(80*sizeof(char)); 
   if ( name != NULL ) { 
      printf("\nEnter your name: "); 
      gets(name); 
      printf("\nHi %s\n", name); 
      free(name); //free memory resources 
   }  // end if 
} //end main 

The code above generates the following result.





Free and malloc

The following code shows pattern to deal with memory allocation failure.

int *pNumber = (int*)malloc(25*sizeof(int));
if(!pNumber)
{
  // Code to deal with memory allocation failure . . .
}

Releasing Dynamically Allocated Memory

When allocating memory dynamically, you need to release the memory when it is no longer required.

To release the memory, you just write this statement:

free(pNumber);
pNumber = NULL;

The free() function has a formal parameter of type void*, you can pass a pointer of any type as the argument.


    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
/*from www .j  av  a 2 s  .  c  o m*/
    int main(void)
    {
      unsigned long long *pPrimes = NULL;  // Pointer to primes storage area
      int total = 5;                       // Number of primes required

      // Allocate sufficient memory to store the number of primes required
      pPrimes = (unsigned long long*)malloc(total*sizeof(unsigned long long));

      if(!pPrimes){
         printf("Not enough memory.\n");
         return 1;
      }
      free(pPrimes);                      // Release the heap memory . . .
      pPrimes = NULL;                     // . . . and reset the pointer
      return 0;
   }

The code above generates the following result.





Example

In this section, we will create a dynamic array using pointer.

In general, we can declare an array using [] with size. Now we can declare our array with dynamic size.

Basically, when we add a new value, we allocate memory and then attach it to array.


  #include <stdio.h> 
  #include <stdlib.h> 
/*from   w  w  w .  j ava2  s . c  om*/
  int main(int argc, const char* argv[]) { 

    // define dynamic array of pointer 
    int *numbers; // single array pointer 

    // a number of array 
    int N = 10; 

    // allocate memory 
    numbers = malloc( N * sizeof(int)); 

    // set values 
    int i; 
    for(i=0;i<N;i++){ 
      numbers[i] = i+3; 
    } 

    // display values 
    for(i=0;i<N;i++){ 
        printf("%d ",numbers[i]); 
    } 
    printf("\n"); 

    // free memory 
    free(numbers); 

    return 0; 
  } 

The code above generates the following result.

Note

Another sample, we also define dynamic array with multidimensional.

For instance, we create two dimensional dynamic array.


   #include <stdio.h> 
   #include <stdlib.h> 
//w  w  w  . jav  a  2 s  .  c  om
   int main(int argc, const char* argv[]) { 

     // define dynamic array of pointer 
     int **matrix; // two dimensional array pointer 

     // a number of array 
     int M = 3; 
     int N = 5; 

     // allocate memory 
     matrix = malloc( M * sizeof(int*)); 

     // set values 
     int i,j; 
     for(i=0;i<M;i++){ 
       matrix[i] = malloc( N * sizeof(int)); 
       for(j=0;j<N;j++){ 
           matrix[i][j] = i + j; 
       } 
     } 

     // display values 
     for(i=0;i<M;i++){ 
         for(j=0;j<N;j++){ 
             printf("%d ",matrix[i][j]); 
         } 
         printf("\n"); 
     } 

     // free memory 
     free(matrix); 

     return 0; 
   } 

The code above generates the following result.

Memory Allocation with the calloc() Function

The calloc() function that is declared in the stdlib.h header.

And it offers a couple of advantages over malloc().

It allocates memory as a number of elements of a given size.

It initializes the memory that is allocated so that all bytes are zero.

The calloc() function requires two argument values: the number of data items and the size of each data item.

Both arguments are of type size_t.

The address of the area allocated is returned as type void*.

Here's how you could use calloc() to allocate memory for an array of 75 elements of type int:

int *pNumber = (int*) calloc(75, sizeof(int));

The return value will be NULL if it was not possible to allocate the memory requested.

You can let the compiler take care of supplying the cast:

int *pNumber = calloc(75, sizeof(int));

Example


    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
/*from  ww w .  j ava 2s .  co  m*/
    int main(void)
    {
      unsigned long long *pPrimes = NULL;  // Pointer to primes storage area
      int total = 5;                       // Number of primes required

      // Allocate sufficient memory to store the number of primes required
      pPrimes = calloc((size_t)total, sizeof(unsigned long long));
      if (pPrimes == NULL) {
           printf("Not enough memory. It's the end I'm afraid.\n");
           return 1;
      }
      free(pPrimes);                      // Release the heap memory . . .
      pPrimes = NULL;                     // . . . and reset the pointer
      return 0;
   }

The code above generates the following result.

Extending Dynamically Allocated Memory

The realloc() function enables you to reuse or extend memory that you previously allocated using malloc() or calloc() (or realloc()).

The realloc() function expects two argument values: a pointer containing an address that was previously returned by a call to malloc(), calloc(), or realloc() and the size in bytes of the new memory.

Example 3

Individual memory segments acquired by malloc() can be treated much like array members; these memory segments can be referenced with indexes.


#include <stdio.h> 
#include <stdlib.h> 
main() /*  ww w  .j a v a 2 s .co m*/
{ 
   int *numbers; 
   int x; 
   numbers = (int *) malloc(5 * sizeof(int)); 
   if ( numbers == NULL ) 
      return;  // return if malloc is not successful 
   numbers[0] = 100; 
   numbers[1] = 200; 
   numbers[2] = 300; 
   numbers[3] = 400;  
   numbers[4] = 500; 
   printf("\nIndividual memory segments initialized to:\n"); 
   for ( x = 0; x < 5; x++ ) 
      printf("numbers[%d] = %d\n", x, numbers[x]); 
}

The code above generates the following result.

Example 4

The following code shows the expanding contiguous memory and realloc()'s outcome.


#include<stdio.h> 
#include<stdlib.h> 
main() /* w  ww  .  ja  va  2s. co  m*/
{ 
   int *number; 
   int *newNumber; 
   int x; 
   number = malloc(sizeof(int) * 5); 
   if ( number == NULL ) { 
      printf("\nOut of memory!\n"); 
      return; 
   }  // end if 
   printf("\nOriginal memory:\n"); 
   for ( x = 0; x < 5; x++ ) { 
      number[x] = x * 100; 
      printf("number[%d] = %d\n", x, number[x]); 
   }  // end for loop 
   newNumber = realloc(number, 10 * sizeof(int));  
   if ( newNumber == NULL ) { 
      printf("\nOut of memory!\n"); 
      return; 
   } 
   else 
      number = newNumber; 
   //intialize new memory only 
   for ( x = 5; x < 10; x++ ) 
      number[x] = x * 100; 
   printf("\nExpanded memory:\n"); 
   for ( x = 0; x < 10; x++ ) 
      printf("number[%d] = %d\n", x, number[x]); 
   //free memory 
   free(number); 
}

The code above generates the following result.