Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Industrial programming >> Lenguaje C

Asignación dinámica de memoria en C: Dominando malloc, calloc, realloc y free

Antes de sumergirte en la asignación dinámica de memoria en C, es esencial entender cómo se gestiona la memoria en el lenguaje.

Cómo funciona la gestión de memoria en C

Cuando declaras una variable con un tipo primitivo, el compilador asigna espacio para ella en la pila automáticamente. Por ejemplo, un float típicamente ocupa 4 bytes (dependiente de plataforma). Puedes confirmar esto con el operador sizeof:

#include <stdio.h> int main() { float x; printf("El tamaño de float es %d bytes", sizeof(x)); return 0; }

La salida será:

El tamaño de float es 4 bytes

Un array de tamaño especificado también se asigna contiguamente en la pila, con cada elemento ocupando el tamaño de su tipo:

#include <stdio.h> int main() { float arr[10]; printf("El tamaño del array float con 10 elementos es %d", sizeof(arr)); return 0; }

El resultado es:

El tamaño del array float con 10 elementos es 40

Mientras que la asignación en pila es automática, muchos programas requieren memoria cuyo tamaño no se conoce hasta tiempo de ejecución. Esta necesidad se aborda mediante asignación dinámica de memoria, que usa el montículo (heap) en lugar de la pila.

Asignación dinámica de memoria en C

La asignación dinámica implica solicitar y liberar memoria manualmente según se necesite, con punteros rastreando los bloques asignados en el montículo. La biblioteca estándar de C proporciona varias funciones para este propósito:

Exploremos cada función en detalle.

Función malloc()

La función malloc() significa "memory allocation". Reserva un bloque de memoria de un tamaño especificado y retorna un puntero a él. El puntero se castea típicamente al tipo deseado:

ptr = (tipo_cast *) malloc(tamaño_bytes);

Ejemplo:

#include <stdlib.h> int main(){ int *ptr; ptr = malloc(15 * sizeof(*ptr)); /* 15 enteros */ if (ptr != NULL) { *(ptr + 5) = 480; /* sexto elemento */ printf("Valor del 6to entero es %d", *(ptr + 5)); } }

Salida:

Valor del 6to entero es 480

Puntos clave:

  1. Usa sizeof(*ptr) para hacer el código robusto contra cambios de tipo.
  2. Verifica valor de retorno NULL para detectar fallo de asignación.
  3. La memoria asignada es contigua; trátala como array y usa aritmética de punteros.

La asignación dinámica no se limita a tipos primitivos; funciona con estructuras, arrays de caracteres y más.

Función free()

La memoria asignada con malloc(), calloc() o realloc() debe liberarse explícitamente para evitar fugas. La función free() realiza esta tarea:

#include <stdio.h> int main() { int* ptr = malloc(10 * sizeof(*ptr)); if (ptr != NULL){ *(ptr + 2) = 50; printf("Valor del 2do entero es %d", *(ptr + 2)); } free(ptr); }

Salida:

 Valor del 2do entero es 50

Función calloc()

calloc() asigna múltiples bloques de tamaño igual e inicializa cada byte a cero, lo que lo hace ideal para arrays y estructuras que requieren memoria puesta a cero:

ptr = (tipo_cast *) calloc(n, tamaño);

Ejemplo – sumar una secuencia aritmética:

#include <stdio.h> int main() { int i, *ptr, sum = 0; ptr = calloc(10, sizeof(int)); if (ptr == NULL) { printf("Error! memoria no asignada."); exit(0); } for (i = 0; i < 10; ++i) { *(ptr + i) = i; sum += *(ptr + i); } printf("Suma = %d", sum); free(ptr); return 0; }

Resultado:

Suma = 45

calloc() vs. malloc()

Diferencias clave:

Función realloc()

La función realloc() cambia el tamaño de una asignación existente preservando su contenido:

ptr = realloc(ptr, nuevo_tamaño);

Ejemplo – extender un búfer de cadena:

#include <stdio.h> int main () { char *ptr = malloc(10); strcpy(ptr, "Programación"); ptr = realloc(ptr, 20); // agrandar strcat(ptr, " En 'C'"); printf("%s, Dirección = %u", ptr, ptr); free(ptr); return 0; }

Si la reasignación falla, realloc() retorna NULL y el bloque original permanece válido.

Arrays dinámicos

Los arrays dinámicos permiten que el número de elementos crezca durante la ejecución, un patrón común en algoritmos y estructuras de datos:

#include <stdio.h> int main() { int *arr_dynamic = NULL; int elementos = 2, i; arr_dynamic = calloc(elementos, sizeof(int)); for (i = 0; i < elementos; i++) arr_dynamic[i] = i; for (i = 0; i < elementos; i++) printf("arr_dynamic[%d]=%d\n", i, arr_dynamic[i]); elementos = 4; arr_dynamic = realloc(arr_dynamic, elementos * sizeof(int)); printf("Después de realloc\n"); for (i = 2; i < elementos; i++) arr_dynamic[i] = i; for (i = 0; i < elementos; i++) printf("arr_dynamic[%d]=%d\n", i, arr_dynamic[i]); free(arr_dynamic); }

Resultado:

arr_dynamic[0]=0 arr_dynamic[1]=1 Después de realloc arr_dynamic[0]=0 arr_dynamic[1]=1 arr_dynamic[2]=2 arr_dynamic[3]=3

Resumen

Lenguaje C

  1. Entendiendo ROM, PROM, EPROM y EEPROM: Diseño, Programación e Identificación
  2. Fundamentos de C#: Entrada y salida esenciales
  3. Dominando las Sentencias Using en C#: Importaciones, Alias y Directivas Estáticas
  4. Dominando la gestión de memoria en C++: uso experto de new y delete
  5. Cuatro patrones probados para funciones definidas por el usuario en C
  6. Asignación dinámica de memoria en C: Dominando malloc, calloc, realloc y free
  7. Dominando funciones de la biblioteca estándar de C: Guía práctica
  8. Asignación dinámica de arrays en C++: Guía práctica con ejemplos de código
  9. Funciones en C++ Explicadas con Ejemplos de Código Prácticos
  10. Dominando funciones en C: Estructura, declaración y mejores prácticas
  11. Gestión Dinámica de Memoria en C: calloc, malloc y free Explicados