Prev:
Arrays of Pointers and
Pointing to Functions
Next:
An Introduction to Strings
Your computer's memory is a resource - it can run out. The memory usage for program data can increase or decrease as your program runs.
Up until this point, the memory allocation for your program has been handled automatically when compiling. However, sometimes the computer doesn't know how much memory to set aside (for example, when you have an unsized array).
The following functions give you the power to dynamically allocate memory for your variables at RUN-TIME (whilst the program is running). For the past tutorials, memory was allocated when the program was compiled (i.e. COMPILE-TIME).
To use the four functions discussed in this section, you must include the stdlib.h header file.
malloc requires one argument - the number of bytes you want to allocate dynamically.
If the memory allocation was successful, malloc will return a void pointer - you can assign this to a pointer variable, which will store the address of the allocated memory.
If memory allocation failed (for example, if you're out of memory), malloc will return a NULL pointer.
Passing the pointer into free will release the allocated memory - it is good practice to free memory when you've finished with it.
This example will ask you how many integers you'd like to store in an array. It'll then allocate the memory dynamically using malloc and store a certain number of integers, print them out, then releases the used memory using free.
#include <stdio.h>
#include <stdlib.h> /* required for the malloc and free functions */
int main() {
int number;
int *ptr;
int i;
printf("How many ints would you like store? ");
scanf("%d", &number);
ptr = malloc(number*sizeof(int)); /* allocate memory */
if(ptr!=NULL) {
for(i=0 ; i<number ; i++) {
*(ptr+i) = i;
}
for(i=number ; i>0 ; i--) {
printf("%d\n", *(ptr+(i-1))); /* print out in reverse order */
}
free(ptr); /* free allocated memory */
return 0;
}
else {
printf("\nMemory allocation failed - not enough memory.\n");
return 1;
}
}
Output if I entered 3:
How many ints would you like store? 3 |
When I first wrote the example using a Borland compiler, I had to cast the returned pointer like this:
ptr = (int *)malloc(number*sizeof(int));
The above example was tested in MSVC++ but try casting the pointer if your compiler displays an error.
calloc is similar to malloc, but the main difference is that the values stored in the allocated memory space is zero by default. With malloc, the allocated memory could have any value.
calloc requires two arguments. The first is the number of variables you'd like to allocate memory for. The second is the size of each variable.
Like malloc, calloc will return a void pointer if the memory allocation was successful, else it'll return a NULL pointer.
This example shows you how to call calloc and also how to reference the allocated memory using an array index. The initial value of the allocated memory is printed out in the for loop.
#include <stdio.h>
#include <stdlib.h>
/* required for the malloc, calloc and free functions */
int main() {
float *calloc1, *calloc2, *malloc1, *malloc2;
int i;
calloc1 = calloc(3, sizeof(float)); /* might need to cast */
calloc2 = calloc(3, sizeof(float));
malloc1 = malloc(3 * sizeof(float));
malloc2 = malloc(3 * sizeof(float));
if(calloc1!=NULL && calloc2!=NULL && malloc1!=NULL && malloc2!=NULL) {
for(i=0 ; i<3 ; i++) {
printf("calloc1[%d] holds %05.5f, ", i, calloc1[i]);
printf("malloc1[%d] holds %05.5f\n", i, malloc1[i]);
printf("calloc2[%d] holds %05.5f, ", i, *(calloc2+i));
printf("malloc2[%d] holds %05.5f\n", i, *(malloc2+i));
}
free(calloc1);
free(calloc2);
free(malloc1);
free(malloc2);
return 0;
}
else {
printf("Not enough memory\n");
return 1;
}
}
Output:
calloc1[0] holds 0.00000, malloc1[0] holds -431602080.00000 |
On all machines, the calloc1 and calloc2 arrays should hold zeros. Contents of the malloc1 and malloc2 arrays will vary.
Try changing the data type from float to double - the numbers displayed were too long for me to fit onto this web page :)
Now suppose you've allocated a certain number of bytes for an array but later find that you want to add values to it. You could copy everything into a larger array, which is inefficient, or you can allocate more bytes using realloc, without losing your data.
realloc takes two arguments. The first is the pointer referencing the memory. The second is the total number of bytes you want to reallocate.
Passing zero as the second argument is the equivalent of calling free.
Once again, realloc returns a void pointer if successful, else a NULL pointer is returned.
This example uses calloc to allocate enough memory for an int array of five elements. Then realloc is called to extend the array to hold seven elements.
#include<stdio.h>
#include <stdlib.h>
int main() {
int *ptr;
int i;
ptr = calloc(5, sizeof(int));
if(ptr!=NULL) {
*ptr = 1;
*(ptr+1) = 2;
ptr[2] = 4;
ptr[3] = 8;
ptr[4] = 16;
/* ptr[5] = 32; wouldn't assign anything */
ptr = realloc(ptr, 7*sizeof(int));
if(ptr!=NULL) {
printf("Now allocating more memory... \n");
ptr[5] = 32; /* now it's legal! */
ptr[6] = 64;
for(i=0 ; i<7 ; i++) {
printf("ptr[%d] holds %d\n", i, ptr[i]);
}
realloc(ptr,0); /* same as free(ptr); - just fancier! */
return 0;
}
else {
printf("Not enough memory - realloc failed.\n");
return 1;
}
}
else {
printf("Not enough memory - calloc failed.\n");
return 1;
}
}
Output:
Now allocating more memory... |
Notice the two different methods I used when initializing the array: ptr[2] = 4; is the equivalent to *(ptr+2) = 4; (just easier to read!).
Before using realloc, assigning a value to ptr[5] wouldn't cause a compile error. The program would still run, but ptr[5] wouldn't hold the value you assigned.
Prev:
Arrays of Pointers and
Pointing to Functions
Next:
An Introduction to Strings
www.iota-six.co.uk
Copyright © 2001-2003
Unauthorized copying not permitted
Designed and Developed Using Macromedia Studio MX