6.9. Dynamic memory allocation¶
The use of arrays is a problem when we do not know the size of the needed array in advance. The program will not run if we don’t allocate enough memory and it wastes space if we allocate too much memory. In these cases, we can use either calloc() or malloc() to allocate the memory at run-time.
#include <stdlib.h> void *calloc( int, int ); void *malloc( int );
Both of these functions return a pointer to the allocated memory.
calloc will initialize the data to all zero, malloc will not.
Both return NULL if they are unable to allocate the requested memory. Thus we can and should always test to see that the function was successful.
The memory allocated by these functions is located at the bottom of the heap, just above the bss memory section. Thus, if the pointer variable is either static or global, then the allocated memory can be used in the same manner. However, if the pointer is an automatic variable (on the stack), it is important to free the memory before the function exits.
int *a, *b; if ((a = (int *)calloc(N, sizeof(int))) == NULL) { printf("A memory allocation error occurred\n"); exit(1); } if ((b = (int *)malloc(N*sizeof(int))) == NULL) { printf("A memory allocation error occurred\n"); exit(1); } ... free(a); free(b);
In the above example, both a and b can be used as an array as if int a[N], b[N]; had been declared.
With calloc and malloc, N can be a variable. With array declarations, N must be a constant.
The use of sizeof() is recommended to ensure portability of the code to another platform.
Also, notice the use of free() above. free() deallocates memory so that other parts of the program can use the memory. If free() is not used, the program will likely have a memory leak.
6.9.1. Dynamically Allocating a Multi-dimensional Array¶
To dynamically allocate a multi-dimensional array, we just need to
declare a pointer of the right type and cast the return memory
address from malloc accordingly. Refer back to our
description of the data type of a multi-dimensional array
identifier. In the following example, we allocate an array as
int x[5][5]. Note that x is a pointer to a [5] of int
.
#include <stdio.h> #include <stdlib.h> int main(void) { int (*x)[5]; int i,j; if( (x = (int (*)[5])malloc(25*sizeof(int))) == NULL) { fprintf(stderr, "memory allocation error"); return 1; } for(i = 0; i < 5; i++) { for( j = 0; j < 5; j++) { x[i][j] = i+j; printf( "%d ", *(*(x+i) + j)); } printf("\n"); } return 0; }
6.9.2. Allocating More Memory¶
If a dynamically allocated array needs to grow larger, we can use realloc to allocate a new memory section, move the old data to the new location and free the old memory allocation. The first argument to realloc is the pointer to the old memory, the second is the new required size in bytes.
#include <stdlib.h> void *realloc( void *, int );