Allocating memory on the heap¶
We’ve seen how memory is divided into segments, such as text, data, read-only data, and bss. These regions are ideal for storing global variables, constants, and other things that have the same lifetime as the program. They always exist as long as the program does, and they don’t change size, so each one can simply be assigned an address and the compiled code can use that address to find it. However, some data comes and goes while the program is running, or has to grow or shrink, or has a size we won’t know until the program calculates it or encounters input. The most flexible segment of memory for this sort of need is the heap.
We’ve already seen heap allocation with the %ms
conversion in
scanf
, and with getline
. In both cases they read strings
as input, but there is no way of knowing in advance how much input the
user will type, so there is no way to compile in a fixed-size variable
that is sure to be big enough. Instead, those library functions allocate
the needed space on the heap and return a pointer to it. When a program is
done with such memory, it releases it with free
to be used again.
You can write your own code that allocates chunks of memory dynamically
using malloc
, which takes a parameter indicating how much memory
you want in bytes and returns a pointer to the allocated memory. To
find out how much memory you want, sizeof
is invaluable. You can
allocate an array by multiplying the size of each item by the number of
items you want. So, the following program reads in a list of numbers:
first, it reads how many numbers there will be, then it allocates space
for them and reads in that many. Of course, it frees the array when it
is done.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *array;
int count;
int i;
/* how many numbers? */
printf("How many numbers will you provide? ");
scanf("%d", &count);
array = malloc(count * sizeof(array[0]));
/* read in the numbers */
printf("Type at least %d numbers.\n", count);
for (i = 0; i < count; i++)
scanf("%d", &array[i]);
/* print them out nicely */
printf("Here are the numbers: ");
for (i = 0; i + 1 < count; i++)
printf("%d, ", array[i]);
if (count > 0)
printf("%d\n", array[i]);
/* for every malloc a free! */
free(array);
}