En este tema, aprenderemos sobre dos funciones cruciales para la asignación dinámica de memoria en C: calloc y realloc. Estas funciones nos permiten gestionar la memoria de manera eficiente y flexible, adaptándose a las necesidades cambiantes de nuestros programas.

  1. Calloc

Descripción

calloc (clear allocation) es una función que asigna memoria para un número específico de elementos de un tamaño determinado y, además, inicializa todos los bytes a cero.

Sintaxis

void* calloc(size_t num_elements, size_t element_size);
  • num_elements: Número de elementos a asignar.
  • element_size: Tamaño de cada elemento en bytes.

Ejemplo Práctico

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *arr;
    int n = 5;

    // Asignar memoria para un arreglo de 5 enteros
    arr = (int*) calloc(n, sizeof(int));

    // Verificar si la asignación fue exitosa
    if (arr == NULL) {
        printf("Error en la asignación de memoria\n");
        return 1;
    }

    // Imprimir los valores inicializados
    for (int i = 0; i < n; i++) {
        printf("arr[%d] = %d\n", i, arr[i]);
    }

    // Liberar la memoria asignada
    free(arr);

    return 0;
}

Explicación del Código

  1. calloc(n, sizeof(int)) asigna memoria para 5 enteros y los inicializa a cero.
  2. Se verifica si la asignación fue exitosa.
  3. Se imprimen los valores inicializados del arreglo.
  4. Se libera la memoria asignada con free.

  1. Realloc

Descripción

realloc (reallocation) es una función que cambia el tamaño de un bloque de memoria previamente asignado. Puede aumentar o disminuir el tamaño del bloque, y si es necesario, mover el bloque a una nueva ubicación.

Sintaxis

void* realloc(void* ptr, size_t new_size);
  • ptr: Puntero al bloque de memoria previamente asignado.
  • new_size: Nuevo tamaño del bloque de memoria en bytes.

Ejemplo Práctico

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *arr;
    int n = 5;

    // Asignar memoria para un arreglo de 5 enteros
    arr = (int*) malloc(n * sizeof(int));

    // Verificar si la asignación fue exitosa
    if (arr == NULL) {
        printf("Error en la asignación de memoria\n");
        return 1;
    }

    // Inicializar el arreglo
    for (int i = 0; i < n; i++) {
        arr[i] = i + 1;
    }

    // Aumentar el tamaño del arreglo a 10 enteros
    n = 10;
    arr = (int*) realloc(arr, n * sizeof(int));

    // Verificar si la reasignación fue exitosa
    if (arr == NULL) {
        printf("Error en la reasignación de memoria\n");
        return 1;
    }

    // Inicializar los nuevos elementos
    for (int i = 5; i < n; i++) {
        arr[i] = i + 1;
    }

    // Imprimir el arreglo
    for (int i = 0; i < n; i++) {
        printf("arr[%d] = %d\n", i, arr[i]);
    }

    // Liberar la memoria asignada
    free(arr);

    return 0;
}

Explicación del Código

  1. malloc(n * sizeof(int)) asigna memoria para 5 enteros.
  2. Se verifica si la asignación fue exitosa.
  3. Se inicializa el arreglo con valores del 1 al 5.
  4. realloc(arr, n * sizeof(int)) aumenta el tamaño del arreglo a 10 enteros.
  5. Se verifica si la reasignación fue exitosa.
  6. Se inicializan los nuevos elementos del arreglo.
  7. Se imprimen todos los elementos del arreglo.
  8. Se libera la memoria asignada con free.

Ejercicios Prácticos

Ejercicio 1

Escribe un programa en C que:

  1. Asigne memoria para un arreglo de 10 enteros usando calloc.
  2. Inicialice el arreglo con los primeros 10 números pares.
  3. Imprima el contenido del arreglo.
  4. Reasigne la memoria para que el arreglo pueda contener 20 enteros usando realloc.
  5. Inicialice los nuevos elementos con los siguientes 10 números pares.
  6. Imprima el contenido del arreglo actualizado.
  7. Libere la memoria asignada.

Solución del Ejercicio 1

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *arr;
    int n = 10;

    // Asignar memoria para un arreglo de 10 enteros
    arr = (int*) calloc(n, sizeof(int));

    // Verificar si la asignación fue exitosa
    if (arr == NULL) {
        printf("Error en la asignación de memoria\n");
        return 1;
    }

    // Inicializar el arreglo con los primeros 10 números pares
    for (int i = 0; i < n; i++) {
        arr[i] = i * 2;
    }

    // Imprimir el contenido del arreglo
    printf("Arreglo inicial:\n");
    for (int i = 0; i < n; i++) {
        printf("arr[%d] = %d\n", i, arr[i]);
    }

    // Aumentar el tamaño del arreglo a 20 enteros
    n = 20;
    arr = (int*) realloc(arr, n * sizeof(int));

    // Verificar si la reasignación fue exitosa
    if (arr == NULL) {
        printf("Error en la reasignación de memoria\n");
        return 1;
    }

    // Inicializar los nuevos elementos con los siguientes 10 números pares
    for (int i = 10; i < n; i++) {
        arr[i] = i * 2;
    }

    // Imprimir el contenido del arreglo actualizado
    printf("Arreglo actualizado:\n");
    for (int i = 0; i < n; i++) {
        printf("arr[%d] = %d\n", i, arr[i]);
    }

    // Liberar la memoria asignada
    free(arr);

    return 0;
}

Retroalimentación sobre Errores Comunes

  1. No verificar la asignación de memoria: Siempre verifica si calloc o realloc retornan NULL para evitar errores de segmentación.
  2. No inicializar nuevos elementos después de realloc: Los nuevos elementos no están inicializados automáticamente, por lo que debes hacerlo manualmente.
  3. No liberar la memoria asignada: Siempre usa free para liberar la memoria asignada y evitar fugas de memoria.

Conclusión

En esta sección, hemos aprendido cómo usar calloc para asignar e inicializar memoria y realloc para cambiar el tamaño de un bloque de memoria existente. Estas funciones son esenciales para la gestión dinámica de memoria en C, permitiendo que nuestros programas sean más flexibles y eficientes. En el próximo tema, exploraremos cómo manejar fugas de memoria y técnicas de depuración para asegurar que nuestro uso de la memoria sea seguro y eficiente.

Curso de Programación en C

Módulo 1: Introducción a C

Módulo 2: Tipos de Datos y Variables

Módulo 3: Flujo de Control

Módulo 4: Funciones

Módulo 5: Arreglos y Cadenas

Módulo 6: Punteros

Módulo 7: Estructuras y Uniones

Módulo 8: Asignación Dinámica de Memoria

Módulo 9: Manejo de Archivos

Módulo 10: Temas Avanzados

Módulo 11: Mejores Prácticas y Optimización

Módulo 12: Proyecto y Evaluación Final

© Copyright 2024. Todos los derechos reservados