Históricamente, la modularidad surgió como una forma de dividir grandes proyectos en partes lógicas independientes para mejorar la legibilidad, reutilización de código y separación de responsabilidades entre los desarrolladores. En C, la modularidad se realiza a nivel de archivos: archivos fuente (.c) y de encabezado (.h).
El problema al que se enfrentan los programadores es: cómo organizar la interacción entre las partes del código, evitar la duplicación de definiciones, no violar la encapsulación y simplificar la compilación.
La solución es utilizar la separación de interfaz e implementación:
Ejemplo de estructura de código modular:
// mymath.h #ifndef MYMATH_H #define MYMATH_H int add(int, int); #endif // mymath.c #include "mymath.h" int add(int a, int b) { return a + b; } // main.c #include "mymath.h" #include <stdio.h> int main() { printf("%d\n", add(3, 4)); return 0; }
Características clave:
¿Se puede definir una variable con extern en un archivo de encabezado y usarla de manera segura en varios módulos?
¡No! Las variables globales deben definirse solo en un archivo .c, y en los encabezados se deben declarar solo a través de extern. De lo contrario, surgirán errores de enlace debido a "múltiple definición".
¿Es obligatorio incluir cada archivo de encabezado a través de #include solo una vez?
Es necesario envolver cada archivo .h con macros de guardia (#ifndef/#define/#endif), de lo contrario, al incluirlo varias veces surgirán conflictos de declaraciones y errores de compilación.
¿Es posible implementar una encapsulación limpia de datos privados de una estructura (puntero opaco) en C?
Sí. El llamado "puntero opaco" permite ocultar los detalles de la estructura al usuario:
// mystruct.h typedef struct MyStruct MyStruct; MyStruct* create(void); void destroy(MyStruct*); // mystruct.c struct MyStruct { int a; };
Toda la lógica está implementada en un único y largo archivo .c, se repite el código, las variables globales se superponen, surgen errores de enlace.
Ventajas:
Desventajas:
El código está descompuesto por módulos, se utilizan include guards, los datos privados están protegidos a través de punteros opacos.
Ventajas:
Desventajas: