Algo muy poco atractivo para muchos programadores que llegan a C/C++ luego de hacer experiencia en otros lenguajes es la asignación de memoria dinámica (punteros, mallocs y reallocs).
Repasemos un poco de teoría y luego veamos un ejemplo sencillo e indoloro
Las variables y arrays en C/C++ ocupan un espacio de memoria limitado e invariable durante la ejecución de un programa.
Para utilizar variables capaces de "crecer" en tiempo de ejecución, es decir, asignar memoria dinámicamente, es necesario recurrir a los punteros y luego a una serie de funciones útiles para trabajar con ellos (malloc, sizeof, realloc, free).
Los programadores suelen (solemos) escapar al uso de punteros pues si cometemos errores (nos olvidamos de liberar memoria "free", o pisamos memoria o hacemos de nuestros programas verdaderos "chupa-memoria") nuestros programas tienden a volverse "inestables". De todas formas, no es para huir despavoridos, al contrario, simplemente hay que ser precavidos y recuerda "malloc never fails"
Sin más palabras, vamos a ver dos ejemplos bien comentados, en el primero de ellos conoceremos a los famosos punteros y las funciones malloc, sizeof y free. En el segundo ejemplo, agregamos la función realloc.
int* ptr; /* puntero a enteros */
...
/**
* La función malloc reserva un "hueco" (zona de memoria) de un tamaño de, 300 veces el tamaño de un entero (este valor es en bytes).
* También se puede ver el uso del sizeof para indicar obtener el tamaño, en bytes, de un entero.
*/
ptr = (int*)malloc ( 300*sizeof(int) );
...
/**
* Si malloc no puede asignar el espacio indicado (por ejemplo, si no hay memoria disponible) devuelve un puntero nulo.
*/
if (ptr==0) {
fprintf(stderr,"No puedo alocar memoria!"); fflush(stderr);
exit(EXIT_FAILURE)
}
ptr[100] = 16; /* Aquí trabajo con una parte de memoria asginada, zona que antes del malloc no existía */
free(ptr); /* terminado el uso de la memoria, no olvides liberarla */
ptr=NULL; /* Es buena práctica dejar los punteros apuntando a NULL (hacia ningún lado) luego de su uso */
size = 8 * sizeof(char); /* asignamos a size un número, que representa la cantidad de bytes que alocaremos luego*/
/* asignamos un "hueco" de ocho bytes para ptr*/
ptr = (char *) malloc( (size_t) size);
...
/**
* Suponte que necesitamos nos que nos "quedamos cortos" con el espacio de memoria asignado.
* Con la función podemos cambiar el tamaño de una zona de memoria dinámica previamente pedida mediante la instrucción malloc.
*/
size *= 2; /* duplicamos el valor de size */
ptr = (char *) realloc(ptr, (size_t) size);
/**
* Tal como malloc, realloc, si no puede asignar el espacio indicado (por ejemplo, si no hay memoria disponible) devuelve un puntero nulo.
*/
if (ptr==0) {
fprintf(stderr,"No puedo realocar memoria!"); fflush(stderr);
exit(EXIT_FAILURE)
}
...
/**
* Un detalle, no menor, realloc puede devolvernos una zona de memoria en otra posición y el puntero devuelto por realloc puede, por lo tanto, ser diferente al devuelto en primera instancia por malloc.
* No obstante, realloc se encarca que el contenido apuntado por el puntero sea el mismo.
* Es decir, todo este "manejo" de memoria es trasparente para el programador
*/
free(ptr) /* Free the malloc()s */
Un comentario final, estas funciones vistas son estándares de C y se pueden encontrar, donde más que, en la librería (o biblioteca como dicen los puristas) stdlib.
Comentarios: