12.1. Allocating Memory DynamicallyThe two functions for allocating memory, malloc( ) and calloc( ), have slightly different parameters:
Both functions return a pointer to void, also called a typeless pointer. The pointer's value is the address of the first byte in the memory block allocated, or a null pointer if the memory requested is not available. When a program assigns the void pointer to a pointer variable of a different type, the compiler implicitly performs the appropriate type conversion. Some programmers prefer to use an explicit type conversion, however.[*] When you access locations in the allocated memory block, the type of the pointer you use determines how the contents of the location are interpreted. Some examples:
#include <stdlib.h> // Provides function prototypes.
typedef struct { long key;
/* ... more members ... */
} Record; // A structure type.
float *myFunc( size_t n )
{
// Reserve storage for an object of type double.
double *dPtr = malloc( sizeof(double) );
if ( dPtr == NULL ) // Insufficient memory.
{
/* ... Handle the error ... */
return NULL;
}
else // Got the memory: use it.
{
*dPtr = 0.07;
/* ... */
}
// Get storage for two objects of type Record.
Record *rPtr;
if ( ( rPtr = malloc( 2 * sizeof(Record) ) == NULL )
{
/* ... Handle the insufficient-memory error ... */
return NULL;
}
// Get storage for an array of n elements of type float.
float *fPtr = malloc( n * sizeof(float) );
if ( fPtr == NULL )
{
/* ... Handle the error ... */
return NULL;
}
/* ... */
return fPtr;
} It is often useful to initialize every byte of the allocated memory block to zero, which ensures that not only the members of a structure object have the default value zero, but also any padding between the members. In such cases, the calloc( ) function is preferable to malloc( ). The size of the block to be allocated is expressed differently with calloc( ). We can rewrite the statements in the previous example using the calloc( ) function as follows: // Get storage for an object of type double. double *dPtr = calloc( 1, sizeof(double) ); // Get storage for two objects of type Record. Record *rPtr; if ( ( rPtr = calloc( 2, sizeof(Record) ) == NULL ) { /* ... Handle the insufficient-memory error ... */ } // Get storage for an array of n elements of type float. float *fPtr = calloc( n, sizeof(float)); |