Modularización
en C
Subprogramas, Funciones, Procedimientos y el arte de dividir para conquistar.
↓ scroll para continuar
¿Qué es Modularizar?
Dividir un problema grande en partes pequeñas y manejables
✗ El Monolito
✓ Modularizado
ANALOGÍA
No esculpís desde una roca entera — construyés con LEGO. Cada pieza tiene forma definida, encaja con otras, y la podés reusar en cualquier construcción.
Subprogramas
En C, todo subprograma es una función. No hay otra cosa.
Anatomía de una Función
int resultado = a + b;
return resultado;
}
REUTILIZACIÓN
Una vez definida, la función puede llamarse infinitas veces desde cualquier parte del programa.
ABSTRACCIÓN
No necesitás saber cómo funciona para usarla. Solo qué recibe y qué devuelve.
int y = sumar(100, 200); // y = 300
int z = sumar(x, y); // z = 310
Funciones vs Procedimientos
La diferencia está en si devuelven algo o no
PROCEDIMIENTO
void — ejecuta una acción, no retorna nada
Como un trabajador que hace la tarea y ya
printf("1. Ingresar\n");
printf("2. Salir\n");
// no hay return
}
FUNCIÓN
con tipo de retorno — calcula y devuelve un valor
Como un trabajador que trae de vuelta el resultado
return a + b;
}
int r = sumar(3, 4); // r = 7
Variables Locales
Viven dentro de la función. Cuando termina, desaparecen.
STACK DE EJECUCIÓN
Cada llamada apila un nuevo "cajón" con sus vars locales
int area = base * altura;
return area;
}
int main() {
int r = calcular(10, 5);
// 'area' DOES NOT exist here
// printf("%d", area); → ERROR
}
⚠ Error de compilación
Intentar usar area fuera de calcular() falla. La variable local no existe fuera de su scope. El compilador te lo dice en la cara.
Variables Globales
Declaradas fuera de toda función. Todos pueden verlas... y modificarlas.
VARIABLE GLOBAL
void incrementar() {
contador++;
}
void resetear() {
contador = 0;
}
int main() {
incrementar();
incrementar();
resetear(); // surprise!
}
⚠ PELIGRO: Efecto Fantasma
resetear() modifica contador sin que nadie lo espere. Este tipo de bug es una pesadilla para debuggear.
Usá globales solo cuando sea estrictamente necesario.
Locales vs Globales
Y el misterio del shadowing: cuándo una variable oculta a otra
void miFuncion() {
int x = 5; // LOCAL x — HIDES the global
printf("%d", x); // prints 5, not 100
} // the local x disappears here
int main() {
printf("%d", x); // prints 100 (the global)
miFuncion(); // prints 5
printf("%d", x); // still 100
}
LOCAL (cyan)
Existe solo dentro de su bloque. Tiene prioridad sobre la global del mismo nombre dentro de ese scope. Cuando el bloque termina, desaparece del stack.
GLOBAL (amber)
Visible desde cualquier función. Si una función tiene una local del mismo nombre, la global queda oculta (shadowed) dentro de esa función.
Pasaje Por Valor
Se copia el valor. El original queda intacto.
x vale 5 en el frame de main n inc(), n pasa a valer 6 (n++) n desaparece. x sigue valiendo 5. El original no fue tocado. n++; // modifies the copy, not the original
}
int main() {
int x = 5;
inc(x); // passes a COPY of x
printf("%d", x); // prints 5 — unchanged
}
Pasaje Por Referencia
Se pasa la dirección de memoria. El original SÍ se modifica.
x vale 5 en dirección 0xFF01 &x (la dirección) se pasa. El puntero p recibe 0xFF01 *p = 10 sigue la dirección y modifica la memoria en 0xFF01 p desaparece, pero el daño está hecho. x ahora vale 10. El original fue modificado. *p = 10; // dereference: modifies what it points to
}
int main() {
int x = 5;
cambiar(&x); // passes the ADDRESS of x
printf("%d", x); // prints 10 — was modified
}
Valor vs Referencia
Mismo punto de partida, resultado completamente distinto
POR VALOR
POR REFERENCIA
| Aspecto | Por Valor | Por Referencia (puntero) |
|---|---|---|
| Qué se pasa | Copia del valor | Dirección de memoria |
| Modifica original | NO ✔ | SÍ ⚠ |
| Sintaxis en llamada | func(x) | func(&x) |
| Sintaxis en parámetro | int n | int *p |
| Cuándo usar | Leer datos, calcular | Modificar el original |
Parámetros Nominales y Efectivos
Definición vs llamada. Placeholder vs valor real.
PARÁMETROS NOMINALES
Los de la DEFINICIÓN — son placeholders, variables locales
return base * altura;
}
Son como variables normales dentro de la función. Se les asigna valor en la llamada.
PARÁMETROS EFECTIVOS
Los de la LLAMADA — los valores reales que se pasan
Son los valores concretos (literales, variables o expresiones) que se envían en la llamada.
CORRESPONDENCIA POSICIONAL — el orden importa
// base=10, altura=20 → result = 200
// Order DOES matter in many cases:
dividir(10, 2); // 10 / 2 = 5
dividir(2, 10); // 2 / 10 = 0 (VERY different result)
Ejemplo Completo
Un programa que usa TODO lo que vimos
// GLOBAL: visible in all functions
int llamadas = 0;
// FUNCTION: returns the area (by value)
int areaRectangulo(int base, int altura) {
llamadas++; // modifies global
int area = base * altura; // LOCAL
return area;
}
// PROCEDURE: prints (void, no return)
void imprimirResultado(int valor) {
printf("Resultado: %d\n", valor);
}
// BY REFERENCE: duplicates the original
void duplicar(int *p) {
*p *= 2;
}
int main() {
// formals: base, altura — actuals: 5, 10
int area = areaRectangulo(5, 10);
imprimirResultado(area); // 50
duplicar(&area); // passes address — by reference
imprimirResultado(area); // 100
printf("Llamadas: %d\n", llamadas); // 1
return 0;
}
GLOBAL
llamadas — visible en todas las funciones
LOCAL
area dentro de areaRectangulo — solo ahí
PUNTERO
*p en duplicar — modifica el original
Reglas de Oro
Grabátelas. Para siempre.
Modularizá: funciones cortas que hacen UNA cosa
Si tu función necesita un comentario explicando qué hace, es demasiado larga.
Preferí variables locales sobre globales
Las globales crean dependencias ocultas y bugs imposibles de rastrear.
Paso por valor: seguro, el original no cambia
Usálo cuando solo necesitás leer o calcular algo a partir del dato.
Paso por referencia (*punteros): cuando NECESITÁS modificar el original
Sé explícito. Quien lee el código necesita saber que la función tiene efectos secundarios.
Parámetros nominales = definición, efectivos = llamada
El orden de los efectivos tiene que coincidir con el de los nominales. Siempre.
Cada función = una responsabilidad
Single Responsibility Principle. Vale en C, vale en cualquier lenguaje, vale en cualquier paradigma.
SESIÓN FINALIZADA
Ahora sabés modularizar en C. Ahora pensá en módulos.
PROGRAMIERDS — 2026