Texto del documento
UT4. Programación modular en C: funciones y bibliotecas Iniciación a la programación orientada a las telecomunicaciones Fernando Martínez Martí Curso 2025 - 2026 Contenidos Introducción Funciones en C Diagramas de flujo de funciones Programación multifichero Bibliotecas en C Buenas prácticas 2 / 27 ¿Qué es la Programación Modular? Concepto Dividir un programa en partes más pequeñas (funciones o módulos) que cooperan para resolver un pro- blema mayor. Analogía Como construir con LEGO: cada pieza tiene su función, pero juntas crean algo más grande.
Beneficios Mayor legibilidad Depuración más sencilla Reutilización del código Trabajo en equipo eficiente 3 / 27 Herramientas de Modularidad en C Funciones Bloques reutilizables Archivos .c y .h Bibliotecas Estándar y externas 4 / 27 Anatomía de una Función 1 tipo_retorno nombre(parametros) { 2 // Declaraciones 3 // Instrucciones 4 return valor; 5 } Componentes Tipo de retorno: qué de- vuelve Nombre: identificador úni- co Parámetros: datos de en- trada Cuerpo: lógica de la fun- ción Ejemplo práctico 1 float area_circulo (float radio) { 2 return 3.1416 * radio * radio; 3 } 5 / 27 Prototipos: Declaración Anticipada ¿Por qué necesitamos prototipos?
Cuando usamos una función antes de definirla, el compilador necesita co- nocer su estructura. Sin prototipo p 1 int main () { 2 sumar (3 ,4); // ERROR 3 return 0; 4 } 5 6 int sumar(int a, int b) { 7 return a + b; 8 } Con prototipo 1 int sumar(int a, int b); 2 3 int main () { 4 sumar (3 ,4); // OK 5 return 0; 6 } 7 8 int sumar(int a, int b) { 9 return a + b; 10 } 6 / 27 Parámetros y Valores de Retorno Paso de parámetros en C Por defecto, C pasa parámetros por valor (se copia el valor).
Función con retorno 1 int cuadrado(int x) { 2 return x * x; 3 } 4 5 int main () { 6 int n = cuadrado (5); 7 printf(" %d", n); // 25 8 } Función sin retorno 1 void saludar(char nombre []) { 2 printf("Hola , %s\n", nombre); 3 } 4 5 int main () { 6 saludar("Ana"); 7 } 7 / 27 Ámbito de Variables Variables Locales Declaradas dentro de una función Solo accesibles en esa función Se crean al llamar la función Se destruyen al terminar Ejemplo 1 void funcion () { 2 int x = 10; // Local 3 } Variables Globales Declaradas fuera de funciones Accesibles desde todo el programa Existen durante toda la ejecución Precaución 1 int global = 5; // Global 2 3 void funcion () { 4 global ++; // Modifica 5 } Usar con moderación 8 / 27 Variables Estáticas: La Palabra Clave static ¿Qué hace static?
Conserva el valor de una variable local entre llamadas a la función.
Sin static 1 void contador () { 2 int count = 0; 3 count ++; 4 printf(" %d\n", count) ; 5 } 6 7 int main () { 8 contador (); // Imprime: 1 9 contador (); // Imprime: 1 10 contador (); // Imprime: 1 11 } Con static 1 void contador () { 2 static int count = 0; 3 count ++; 4 printf(" %d\n", count) ; 5 } 6 7 int main () { 8 contador (); // Imprime: 1 9 contador (); // Imprime: 2 10 contador (); // Imprime: 3 11 } 9 / 27 Usos Prácticos de Variables Estáticas Generador de IDs únicos 1 int generar_id_dispositivo () { 2 static int id = 1000; 3 return id ++; 4 } 5 6 int main () { 7 printf("Router: ID= %d\n", 8 generar_id_dispositivo ()); 9 printf("Switch: ID= %d\n", 10 generar_id_dispositivo ()); 11 printf("Access Point: ID= % d\n", 12 generar_id_dispositivo ()); 13 return 0; 14 } Características Se inicializa una sola vez Mantiene su valor Ámbito local a la función Vida durante todo el pro- grama Cuándo usar Contadores Generadores de IDs Caché de valores Estados entre llamadas 10 / 27 Visualizando Funciones: Diagrama de Flujo Inicio Leer radio Llamar area_circulo(r) Mostrar área Fin Flujo principal El programa principal llama a la función y continúa con el resulta- do.
Código correspondiente 1 float r; 2 scanf(" %f", &r); 3 float area = area_circulo (r); 4 printf("Área: %.2f", area ); 11 / 27 Organización en Múltiples Archivos Archivos de Cabecera (.h) Prototipos de funciones Constantes y macros Declaraciones de estructuras matematica.h 1 #ifndef MATEMATICA_H 2 #define MATEMATICA_H 3 4 float area_circulo (float r); 5 int factorial(int n); 6 7 #endif Archivos Fuente (.c) Implementación de funciones Lógica del programa Variables locales matematica.c 1 #include "matematica.h" 2 3 float area_circulo (float r) { 4 return 3.1416 * r * r ; 5 } 6 7 int factorial(int n) { 8 // Implementaci ón 9 } 12 / 27 Estructura Completa de un Proyecto Modular Archivo principal main.c 1 #include <stdio.h> 2 #include "matematica.
h" 3 4 int main () { 5 printf("Área: %.2 f\n", 6 area_circulo (2.0) ); 7 8 printf("5! = %d\n ",factorial (5)); 9 10 return 0; 11 } main.c función main matematica.h prototipos matematica.c definiciones #include usa linking Ventajas ¥ Código organizado ¥ Fácil mantenimiento ¥ Compilación independiente 13 / 27 El Guardián de Inclusión: #ifndef Problema: Inclusión múltiple Si un archivo .h se incluye varias veces, puede causar errores de redefinición.
Sin protección p 1 // matematica.h 2 float area_circulo (float r); 3 int factorial(int n); Si se incluye dos veces: ERROR Con protección § 1 // matematica.h 2 #ifndef MATEMATICA_H 3 #define MATEMATICA_H 4 5 float area_circulo (float r); 6 int factorial(int n); 7 8 #endif 9 Solo se procesa una vez 14 / 27 Bibliotecas Estándar de C <math.h> sqrt, pow, sin, cos <string.h> strlen, strcmp, strcat <stdlib.h> rand, malloc, exit <stdio.h> printf, scanf, fopen Ventaja No reinventes la rueda: usa funciones probadas y optimizadas.
15 / 27 Ejemplo Práctico: Biblioteca <math.h> 1 #include <stdio.h> 2 #include <math.h> 3 4 int main () { 5 double x = 16.0; 6 double y = 2.0; 7 8 printf("Raíz cuadrada de %.0f = %.2f\n", x, sqrt(x)); 9 printf(" %.0f elevado a %.0f = %.2f\n", x, y, pow(x, y)); 10 printf("Seno de 90° = %.2f\n", sin(M_PI /2)); 11 12 return 0; 13 } Nota de compilación En algunos sistemas necesitas: gcc programa.c -lm 16 / 27 El Proceso de Compilación en C 1. Preprocesador #include, #define 2. Compilador .c .o 3.
Enlazador .o ejecutable Expande macros e incluye archivos Genera código objeto (.o) Une todo y crea el programa Archivos intermedios .c .i (preprocesado) .s (ensamblador) .o (objeto) ejecutable 17 / 27 Compilación Manual: Paso a Paso Opción 1: Compilación directa (todo a la vez) gcc main.c matematica.c -o programa Opción 2: Compilación por separado (recomendado) # Paso 1: Compilar a archivos objeto gcc -c main.c -o main.o gcc -c matematica.c -o matematica.o # Paso 2: Enlazar los archivos objeto gcc main.o matematica.o -o programa # Paso 3: Ejecutar ./programa Ventaja de compilación separada Si modificas solo main.c, solo recompilas main.o 18 / 27 Opciones Útiles de GCC Banderas de compilación más comunes -c Compilar sin enlazar (genera .o) -o nombre Especificar nombre del ejecutable -Wall Mostrar todos los warnings -g Incluir información de depuración -lm Enlazar con biblioteca matemática -std=c11 Usar estándar C11 Ejemplo con múltiples opciones gcc -Wall -g -std=c11 main.c matematica.c -o programa -lm Importante .
La opción -lm debe ir al final cuando usas <math.h> 19 / 27 ¿Qué es un Makefile? Definición Un Makefile es un archivo que automatiza el proceso de compilación, es- pecificando: Qué archivos compilar En qué orden Qué dependencias tienen Sin Makefile gcc -c main.c gcc -c matematica.c gcc main.o matematica.o -o programa ¡Tedioso para proyectos grandes! Con Makefile make ¡Un solo comando!
Ventajas Automatización Detecta cambios Recompila solo lo necesario 20 / 27 Estructura Básica de un Makefile Sintaxis fundamental objetivo: dependencias comando Importante: El comando debe empezar con un TAB, no espacios Ejemplo simple programa: main.o matematica.o gcc main.o matematica.o -o programa main.o: main.c matematica.h gcc -c main.c matematica.o: matematica.c matematica.h gcc -c matematica.c Cómo funciona make verifica si las dependencias son más nuevas que el objetivo 21 / 27 Makefile Completo y Profesional Makefile con variables y reglas # Variables CC = gcc CFLAGS = -Wall -g -std=c11 LIBS = -lm TARGET = programa OBJS = main.o matematica.o # Regla principal all: $(TARGET) # Crear ejecutable $(TARGET): $(OBJS) $(CC) $(OBJS) -o $(TARGET) $(LIBS) # Compilar archivos objeto main.o: main.c matematica.h $(CC) $(CFLAGS) -c main.c matematica.o: matematica.c matematica.h $(CC) $(CFLAGS) -c matematica.c 22 / 27 Makefile: Reglas de Limpieza Continuación del Makefile # Limpiar archivos generados clean: rm -f $(OBJS) $(TARGET) # Recompilar todo desde cero rebuild: clean all Uso de variables Las variables ($(CC), $(CFLAGS), etc.) permiten cambiar configuraciones fácilmente en un solo lugar 23 / 27 Usando el Makefile Comandos básicos # Compilar el proyecto make # O explícitamente make all # Limpiar archivos make clean # Recompilar todo make rebuild Flujo de trabajo típico 1 Editar código fuente 2 Ejecutar make 3 Probar el programa 4 Si hay errores, volver a 1 5 make clean para limpiar Recuerda ò El nombre del archivo debe ser exactamente Makefile o makefile ò Los comandos deben empezar con TAB, no espacios 24 / 27 Buenas Prácticas en Programación Modular Recomendaciones Una función = una tarea Nombres descriptivos Documentar funciones Reutilizar código Usar bibliotecas estándar p Evitar Funciones muy largas Variables globales excesivas Código duplicado Nombres ambiguos Falta de comentarios Regla de oro Si una función hace más de una cosa, divídela.
25 / 27 Documentando Funciones Ejemplo de documentación completa 1 /** 2 * Calcula el área de un círculo 3 * 4 * @param radio El radio del círculo (debe ser >= 0) 5 * @return El área calculada (pi*r^2) 6 * @note Usa el valor de pi = 3.1416 7 */ 8 float area_circulo (float radio) { 9 return 3.1416 * radio * radio; 10 } Beneficios Tu yo del futuro (y tus compañeros) te lo agradecerán. 26 / 27 ¡Gracias! Cualquier pregunta será bienvenida fmartinezmarti@educa.madrid.org IES Pacífico