[Univ of Cambridge] [Dept of Engineering]
next up previous contents
Next: Input/Output Up: ANSI C for Programmers Previous: Declarations

Memory Allocation

Space is automatically set aside for variables when they are defined, but sometimes you don't know beforehand how many variables you'll need or just how long an array might need to be. The malloc command creates space, returning a pointer to this new area. To illustrate its use and dangers, here's a sequence of attempts at writing a string reverser program.

#include <stdio.h>
#include <stdlib.h>
void print_reverse(char *str)
{
int i;
unsigned int len;

len = strlen(str) - 1; /* Why the -1? Because arrays start at 0,
                          so if a string has n chars, the 
                          last char will be at position n-1 
                        */
for (i=len; i>=0; i--)
    putchar(str[i]);
}

void main()
{
char input_str[100] /* why 100? */
  printf("Input a string\n");
  gets(input_str);  /* should check return value */
  printf("String was %s\n", input_str);
  print_reverse(input_str);
}

This works, but is a bit `loose' (suppose the user types more than 100 characters?) and doesn't keep a copy of the reversed string should it be needed later. The next example shows a wrong (but not uncommon) attempt to solve the latter limitation.

#include <stdio.h>
/* WRONG! */
char* make_reverse(char *str)
{
int i, j;
unsigned int len;
char newstr[100];
len = strlen(str) - 1;
j=0;

for (i=len; i>=0; i--;)
    newstr[j] = str[i];
    j++;
/* now return a pointer to this new string */
return newstr;
}

void main()
{
char input_str[100]; /* why 100? */
char *c_ptr;
  printf("Input a string\n");
  gets(input_str);  /* should check return value */
  c_ptr = make_reverse(input_str); 
  printf("String was %s\n", input_str);
  printf("Reversed string is %s\n", c_ptr);  
}

Like many flawed C programs this will work much of the time, especially if it's not part of a bigger program. The problems are that :-

Let's try again.  
/* mallocing.c */
#include <stdio.h>
#include <stdlib.h>
char* make_reverse(char *str)
{
int i;
unsigned int len;
char *ret_str, *c_ptr;
len = strlen(str);

 /* Create enough space for the string AND the final \0.
  */
 ret_str = (char*) malloc(len +1); 
 /*
    Now ret_str points to a `permanent' area of memory.
  */

 /* Point c_ptr to where the final  '\0' goes and put it in */
 c_ptr = ret_str + len;
 *c_ptr = '\0';

 /* now copy characters from str into the newly created space.
    The str pointer will be advanced a char at a time,
    the cptr pointer will be decremented a char at a time. 
  */
 while(*str !=0){ /* while str isn't pointing to the  last '\0' */
   c_ptr--;
   *c_ptr = *str;
   str++; /* increment the pointer so that it points to each
            character in turn. */
 }
 return ret_str;
}

void main()
{
char input_str[100]; /* why 100? */
char *c_ptr;
  printf("Input a string\n");
  gets(input_str);  /* Should check return value */
  c_ptr = make_reverse(input_str); 
  printf("String was %s\n", input_str);
  printf("Reversed string is %s\n", c_ptr);  
}

The malloc'ed space will be preserved until it is explicitly freed (in this case by doing `free(c_ptr)'). Note that the pointer to the malloc'ed space is the only way you have to access that memory: lose it and the memory will be inaccessible. It will only be freed when the program finishes.

malloc is often used to create tree and list structures, since one often doesn't know beforehand how many items will be needed. See section A.4 for an example.


next up previous contents
Next: Input/Output Up: ANSI C for Programmers Previous: Declarations
Tim Love
1999-10-06