En muchas ocaciones no queremos crear un arreglo que se utilice sólo la memoria necesaria en tiempo de ejecución. Sin embargo no resulta tan claro crear este tipo de arreglos de forma dinámica. Peor aún, si creamos un arreglo dentro de una función y queremos devolver el valor de un arreglo estático esto sería imposible, ya que como es una variable local de la función se elimina antes de poder pasar el valor. Por lo tanto incluyo este pequeño código para poder realizar estas funciones

 

Como muestra la imagen primero reservaremos memoria para un puntero en forma de arreglo de una dimensión que a su vez tendrá punteros, lo que llamamos un arreglo de punteros. Una vez reservados el espacio para el arreglo de punteros iteraremos sobre este para reservar la memoria necesaria para los elementos de cada uno de los nuevos arreglos a los cuales apuntamos. 

#include <stdlib.h>
#define FREE(p) do { free(p); (p) = NULL; } while(0)

int **alloc_array(int, int);
void free_array(int **, int);

int **alloc_array(int x_size, int y_size)
{
int i;
int **array;
array = malloc(x_size * sizeof(int *));
if(array == NULL)
{
return NULL;
}
for(i = 0; i < x_size; i++)
{
array[i] = malloc(y_size * sizeof(int));
if(array[i] == NULL)
{
return NULL;
}
}
return array;
}

void free_array(int **array, int x_size)
{
int i;
for(i = 0; i < x_size; i++)
FREE(array[i]);
FREE(array);
}

Como vemos, tambien es necesario liberar la memoria que hemos reservado para nuestro arreglo. Es necesario hacer esto para cada una de las variables y a su vez referenciar todos los punteros a NULL.