Allocating Memory Storage at Runtime in C

The C library has functions for allocating memory storage space at runtime via a process called dynamic memory allocation. The advantage of dynamic memory allocation over static memory allocation is that we are not required to know how how much memory the program will need before executing the program. All of Cs dynamic memory allocation functions are stored in stdlib.h.

There are four dynamic memory allocation functions that we should know: calloc(), malloc(), realloc(), and free(). The two core functions are malloc() and free(). Each time malloc() is called, a section of free memory is allocated from the heap. Each time free() is called, memory is returned to the system’s heap.

Since we haven’t looked at it previously, first let’s work with calloc(). The calloc() function takes two arguments, whereas the malloc() function takes only one. The first argument is the number of items to allocate memory for, and the second argument is the size of each item in memory. The calloc() function returns a pointer to the first byte of the allocated memory. If there is not enough memory, a null pointer is returned.

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

double *getMem(int numElements);

int main(void){
    
    int i = 0;

    double *ptrToDoubles = getMem(100);
    
    double *ptrToStart = ptrToDoubles;
    
    while(i++ < 100){
        *(ptrToDoubles++) = i * .1587;
    }

    printf("double Array begins at location %p\n", ptrToStart);
    printf("and ends at location %p\n", ptrToDoubles);    

    ptrToDoubles = ptrToStart;

    //print out first item in 
    //dynamic double array
    printf("first element is %f\n",*ptrToDoubles);

    //print out last item in 
    //dynamic doubles array
    printf("last element is %f\n", *(ptrToDoubles+99));

    //free the memory!
    free(ptrToDoubles);
}

double *getMem(int numElements){

    double *ptr;
    
    ptr = calloc(numElements, sizeof(double));

    if(!ptr){
        printf("Allocation error.\n");
        exit(1);
    }

    return ptr;

}

As we have seen above, the free() function returns the memory pointed to by its argument to the heap.

Rather than allocating a group of bytes as malloc() does, calloc() allocates a group of data elements of a set size.

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


int main(void){
    
    //number of elements to create
    unsigned n;
    //index num
    int i;

    int value;    

    int *p;

    printf("How many numbers of type int do you want to allocate?\n");

    scanf(" %u", &n);

    p = calloc(n, sizeof(int));

    if(p!=NULL){
        printf("Memory allocation successful!\n");
    } else {
        printf("Memory allocaion failed!\n");
        return 1;
    }

    while(1){
        printf("What element would you like to assign a value to?");
        printf("(Enter negative number to finish assigning values)\n");

        scanf(" %d", &i);
        if(i < 0){
            break;
        }

        //check if index is within range
        if(i >= n){
            printf("Index out of range.\n");
            continue;
        }

        printf("What value would you like to assign to it?\n");
        scanf(" %d", &value);

        *(p+i) = value;

    }

    //print out values
    i = 0;
    printf("The dynamic int array contains: \n");
    while(i < n){
        printf("%d\n", *(p+i));
        i++;    
    }

    free(p);

    return 0;

}

Note that unlike malloc(), the calloc() function also initializes the stored memory to all zeros, which means that calloc() is slightly slower than malloc().

The malloc() function returns a pointer to the first byte in memory of the size specified as its argument. If there is insufficient memory, the malloc() function will return a null pointer. We should verify that the return value is not null before attempting to use it.

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

struct name{
    char firstName[50];
    char lastName[50];    
};

//returns pointer to name struct
//exits on failure to allocate
struct name *getNameStruct(void){
    struct name *ptr;
    
    if((ptr = malloc(sizeof(struct name)))==NULL){
        printf("Allocation Error.\n");
        exit(1);
    }

    return ptr;

};

int main(void){

    struct name *myName = getNameStruct();
    
    strcpy(myName->firstName, "Al");
    strcpy(myName->lastName, "Jensen");

    printf("First Name %s\n", myName->firstName);
    printf("Last Name %s\n", myName->lastName);

    free(myName);

    return 0;

}

The realloc() function changes the size of a block of memory that was previously allocated by malloc() or calloc(). The first argument is a pointer to the original block of memory. The second argument is the size, in bytes, of the new block.

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


int main(void){
    
    char *ptr1;
    char *ptr2;
    char *ptr3;

    ptr1 = malloc(18 * sizeof(char));

    if(!ptr1){
        printf("Allocation Error.\n");
        return 1;
    }

    strcpy(ptr1, "This is 17 chars.");

    printf("%s\n", ptr1);

    ptr2 = malloc(22 * sizeof(char));

    if(!ptr2){
        printf("Allocation Error.\n");
        return 1;
    }

    strcpy(ptr2, "But this is 21 chars.");    

    ptr3 = realloc(ptr1, 40);
    
    strcat(ptr3, ptr2);

    printf("%s\n", ptr3);    

    //free memory
    //note that ptr3 is reallocated
    //storage of ptr1
    free(ptr2);
    free(ptr3);

    return 0;

}

if you can, please take the time to visit my Amazon.com author page at  http://www.amazon.com/Al-Jensen/e/B008MN382O

 

 

 

 

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s