Asignación dinámica de memoria en C: Dominando malloc, calloc, realloc y free
Asignación dinámica de memoria en C
Esta guía le guía a través de la asignación dinámica de memoria en C usando las funciones de la biblioteca estándar malloc(), calloc(), realloc() y free(), con ejemplos claros y consejos de buenas prácticas.
¿Por qué usar asignación dinámica?
Los arrays estáticos tienen un tamaño fijo declarado en tiempo de compilación, lo que puede llevar a espacio desperdiciado o capacidad insuficiente durante la ejecución. La asignación dinámica le permite solicitar exactamente la cantidad de memoria que necesita mientras el programa se ejecuta.
Las cuatro funciones están definidas en el encabezado <stdlib.h> y proporcionan una forma controlada de gestionar la memoria del heap.
malloc() – Asignar un bloque de bytes
El nombre malloc significa "memory allocation" (asignación de memoria). Reserva un bloque contiguo de memoria del tamaño especificado (en bytes) y devuelve un puntero de tipo void * que puede convertirse a cualquier otro tipo de puntero.
Sintaxis
ptr = malloc(tamaño_en_bytes); // convertir al tipo deseado si es necesario
Ejemplo
float *ptr = malloc(100 * sizeof(float)); // 400 bytes en la mayoría de sistemas
Aquí, ptr apunta al primer byte de un bloque de 400 bytes. Si la solicitud falla, malloc devuelve NULL. Se recomienda evitar conversiones innecesarias en C; el compilador puede deducir el tipo al asignar el resultado a un puntero tipado.
calloc() – Asignar e inicializar a cero
calloc significa "contiguous allocation" (asignación contigua). A diferencia de malloc, inicializa cada bit del bloque asignado a cero, lo que lo hace seguro para tipos numéricos y punteros.
Sintaxis
ptr = calloc(num_elementos, tamaño_de_cada_elemento);
Ejemplo
float *ptr = calloc(25, sizeof(float)); // 25 elementos float inicializados a cero
El puntero devuelto es NULL si la asignación falla.
free() – Liberar memoria asignada
La memoria obtenida con malloc o calloc persiste hasta que la libere explícitamente. free() desasigna el bloque y devuelve la memoria al heap para reutilización futura.
Sintaxis
free(ptr);
Llamar a free con un puntero NULL es seguro y no hace nada.
Ejemplo 1: Usando malloc() y free()
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int n, i, *ptr, sum = 0;
printf("Introduzca número de elementos: ");
scanf("%d", &n);
ptr = malloc(n * sizeof(int));
if (!ptr) {
fprintf(stderr, "Error: memoria no asignada.\n");
return EXIT_FAILURE;
}
printf("Introduzca elementos: ");
for (i = 0; i < n; ++i) {
scanf("%d", ptr + i);
sum += *(ptr + i);
}
printf("Suma = %d\n", sum);
free(ptr);
return EXIT_SUCCESS;
}
Salida
Introduzca número de elementos: 3
Introduzca elementos: 100 20 36
Suma = 156
Ejemplo 2: Usando calloc() y free()
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int n, i, *ptr, sum = 0;
printf("Introduzca número de elementos: ");
scanf("%d", &n);
ptr = calloc(n, sizeof(int));
if (!ptr) {
fprintf(stderr, "Error: memoria no asignada.\n");
return EXIT_FAILURE;
}
printf("Introduzca elementos: ");
for (i = 0; i < n; ++i) {
scanf("%d", ptr + i);
sum += *(ptr + i);
}
printf("Suma = %d\n", sum);
free(ptr);
return EXIT_SUCCESS;
}
Salida
Introduzca número de elementos: 3
Introduzca elementos: 100 20 36
Suma = 156
realloc() – Redimensionar una asignación existente
Si descubre que su asignación actual es demasiado pequeña o más grande de lo necesario, realloc() ajusta el tamaño preservando los datos existentes (hasta el nuevo tamaño).
Sintaxis
ptr = realloc(ptr, nuevo_tamaño_en_bytes);
Devuelve un puntero al bloque reasignado o NULL en caso de fallo. Para evitar fugas de memoria, guarde el resultado en un puntero temporal primero.
Ejemplo 3: Usando realloc()
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int *ptr, i, n1, n2;
printf("Introduzca tamaño inicial: ");
scanf("%d", &n1);
ptr = malloc(n1 * sizeof(int));
if (!ptr) {
fprintf(stderr, "Asignación fallida.\n");
return EXIT_FAILURE;
}
printf("Direcciones antes de reasignación:\n");
for (i = 0; i < n1; ++i) printf("%p\n", ptr + i);
printf("\nIntroduzca nuevo tamaño: ");
scanf("%d", &n2);
int *tmp = realloc(ptr, n2 * sizeof(int));
if (!tmp) {
fprintf(stderr, "Reasignación fallida.\n");
free(ptr);
return EXIT_FAILURE;
}
ptr = tmp;
printf("Direcciones después de reasignación:\n");
for (i = 0; i < n2; ++i) printf("%p\n", ptr + i);
free(ptr);
return EXIT_SUCCESS;
}
Salida típica
Introduzca tamaño inicial: 2
Direcciones antes de reasignación:
0x7ffc12345670
0x7ffc12345674
Introduzca nuevo tamaño: 4
Direcciones después de reasignación:
0x7ffc12345670
0x7ffc12345674
0x7ffc12345678
0x7ffc1234567c
Al dominar estas cuatro funciones y aplicar un manejo de errores adecuado, puede gestionar la memoria del heap de forma segura y eficiente en cualquier aplicación C.
Lenguaje C
- Entendiendo ROM, PROM, EPROM y EEPROM: Diseño, Programación e Identificación
- Microprocesadores: La Evolución de la Computación con Programa Almacenado
- El Precio Dinámico Regresa al Comercio Minorista Tradicional: Por Qué Es Inevitable
- Cervoz lanza memoria DDR4‑2666 avanzada para soluciones industriales de IA e IoT
- Dominando la gestión de memoria en C++: uso experto de new y delete
- Asignación dinámica de arrays en C++: Guía práctica con ejemplos de código
- calloc() en C: Asignación de memoria inicializada a cero y ejemplo práctico
- Uso de realloc() en C: Sintaxis, mejores prácticas y ejemplo
- Gestión Dinámica de Memoria en C: calloc, malloc y free Explicados
- Dominando la Memoria Dinámica en C++: Stack vs Heap Explicado
- Mejoras en Java 10: Asignar Heap en NV-DIMM con -XX:AllocateHeapAt