Lección 2 · 2 de 20
Memoria dinámica: malloc, calloc y free · C
Reserve memoria en tiempo de ejecución en C con malloc y calloc, compruebe NULL y libérela con free: las notas de una clase y su histograma.

Un array normal tiene un tamaño fijo al compilar. Cuando el tamaño se conoce solo al ejecutar (cuántos alumnos hay en un archivo, por ejemplo), se pide la memoria al montón (*heap*) con `malloc`, que recibe un número de bytes y devuelve un puntero al bloque.
malloc(students * sizeof *marks) pide sitio para 10 int. Escribir sizeof *marks en vez de sizeof(int) hace que el cálculo siga siendo correcto si un día cambia el tipo del puntero. Si no hay memoria, malloc devuelve NULL, y hay que comprobarlo antes de usar el bloque.
Lo que devuelve malloc no está inicializado: contiene lo que hubiera antes. Por eso el bucle escribe cada nota antes de leerla. **calloc(11, sizeof *count)** reserva 11 contadores y además los pone a cero, justo lo que hace falta para contar cuántas veces sale cada nota con count[marks[i]]++.
Cada bloque reservado se devuelve con `free` exactamente una vez. Si falla el segundo calloc, el programa libera primero marks antes de salir. Después de free, el puntero sigue guardando la dirección antigua (un puntero colgante); ponerlo a NULL evita usarlo por error.
Olvidar un free es una fuga de memoria: en un programa corto no se nota, pero en un servidor que funciona días acaba agotando la memoria.
Código · main.c
#include <stdio.h>#include <stdlib.h>int main(void) { int students = 10; // known only at run time in a real program // malloc: room for 10 ints. Its contents are garbage until we write them. int *marks = malloc(students * sizeof *marks); if (marks == NULL) { fprintf(stderr, "Out of memory\n"); return 1; } for (int i = 0; i < students; i++) marks[i] = (i * 7 + 3) % 6 + 5; // marks from 5 to 10 // calloc: room for 11 counters, all set to zero. Ideal for counting. int *count = calloc(11, sizeof *count); if (count == NULL) { free(marks); return 1; } for (int i = 0; i < students; i++) count[marks[i]]++; printf("Marks:"); for (int i = 0; i < students; i++) printf(" %d", marks[i]); printf("\n"); for (int m = 5; m <= 10; m++) { printf("%2d | ", m); for (int k = 0; k < count[m]; k++) printf("*"); printf(" %d\n", count[m]); } free(count); // every malloc or calloc needs exactly one free free(marks); marks = NULL; // a freed pointer must not be used again return 0;}Salida · cc main.c -o main && ./main
Marks: 8 9 10 5 6 7 8 9 10 5 5 | ** 2 6 | * 1 7 | * 1 8 | ** 2 9 | ** 2 10 | ** 2
Para recordar
malloc(n * sizeof *p)reserva sin inicializar.calloc(n, sizeof *p)reserva y pone todo a cero.- Compruebe siempre si devuelven
NULL. - Un
freepor cada reserva, y no use el puntero después.
Ejercicio
Cambie el programa para que también calcule la media: reserve con malloc un array de double con la nota de cada alumno sobre 100 (nota × 10), escríbalo y libérelo al final.