2. Grandes Programas
Cuando se escriben grandes programas se debe generar un proyecto el cual
será dividido en módulos. Donde solo uno de ellos contiene el archivo main().c
Los demás archivos contienen las demás funciones que el programa requiera.
VENTAJAS
-Los módulos se dividen de manera natural en grupo comunes de funciones.
-Se pueden compilar los modulos separadamente y ligarlos con los ya
compilados.
-Las utilerias como make pueden ayudar a mantener sistemas grandes.
3. Archivos cabecera
Son archivos en los que se almacena un módulo o conjunto de definiciones,
estos archivos tienen la extensión “.h”.
Para definirlos en la función principal o main, basta con escribir algo así
como lo siguiente:
#include "mi_cabecera.h"
Con lo anterior, le estamos diciendo al programa que contenga el archivo
módulo “mi_cabecera.h”
4. Variables y Funciones
Externas
cada variable y argumento definido dentro de las funciones son locales así
mismas, si se desea declarar una variable global es necesario declarar fuera
de dichas funciones.
Alcance de variables externas.
Es decir si una variable externa(Global) es declarada después de la función
main() dicha función no podrá solicitar dicha variable.
5. ALCANCE DE LAS FUNCIONES Y
VARIABLES EN C
Una función es capaz de reconocer todas las variables de tipo global que
hayan sido declaradas antes de la misma función.
Adicionalmente, toda variable declarada dentro de una función se destruye al
finalizar esta.
Esta es la razón por la que todos los prototipos de funciones deben escribirse
o incluirse antes del cuerpo del código.
6. Ejemplo 1
En el código de la derecha describe un ejemplo
en el que en la función “intenta_acceder” intenta
usar la variable que no es global “variable”.
El código no compila.
7. Ejemplo 2
El ejemplo de la derecha muestra un ejemplo en
el que las variables son correctamente definidas
y llamadas pero en cambio las funciones no.
No es posible acceder a la función
“intenta_acceder” desde la función main ya que
esta fué declarada después de esta.
8. Ejemplo 3
El ejemplo 3 es un programa correcto:
La función “intenta_acceder” es llamada
desde la función main y el main si la conoce
ya que fué declarada antes de esta.
Las variables con nombre “variable” son
totalmente diferentes y las funciones
nisiquiera lo pueden notar, cada una es local a
su función y muere al finalizar esta; al llamar a
“intenta_acceder” se genera otro bloque de
memoria que sólo esa función conoce.
9. Variables externas
Son utilizadas cuando se requiere hacer referencia a una variable aún no
declarada o que se encuentra definida en un módulo externo.
La definición de la variable sólo debe hacerse una vez.
Ejemplo de uso:
main.c int arr[100];
arch.c extern int arr[];
10. VENTAJAS
-Es más fácil trabajar en Equipo ya que cada uno puede trabajar en un módulo.
-Puede ser usado un estilo orientado a objetos Cada archivo define un tipo
particular de objeto como un tipo de dato y las operaciones en ese objeto como
funciones. La implementación del objeto puede mantenerse privado al resto del
programa.
-Los archivos pueden contener todas las funciones de un grupo relacionado.
-Objetos bien implementados o definiciones de funciones pueden ser reusadas
en otros programas, con lo que se reduce el tiempo de desarrollo.
-En programas muy grandes cada función principal puede ocupar un propio
archivo.
-Cuando los cambios son hechos a un archivo, solamente ese archivo necesita
ser recompilado para reconstruir el programa.
11. Dividir Un Programa en varios
archivos
cada archivo tendrá que contender una o más funciones y sólo en uno se
incluirá la función main() mientras que los otros serán llamados de otros
archivos tratados como una biblioteca o cabecera.
#include “Archivo1.h” es como declara que en ese programa se utilizará dicho
archivo.
12. Organización de los datos de los datos en
cada archivo
Es importante organizar los datos en un cierto orden en cada uno de los
archivos creados:
1. Cabeceras de archivos y tipos de datos más importantes
2. declaración de variables globales y externas
3. una o más funciones (destacando la importancia de su orden)
Ese dependiendo en cuanto al gusto del programador en uso de funciones
implícita explícita.
13. La utilería make
Esta utilería sirve para mantener en buen funcionamiento un gran conjunto de
módulos de programas. Es muy útil si se desea por ejemplo, compilar varios
archivos .c y algunos de ellos ya fueron previamente compilador: Con la utilería
make podemos evitar compilar nuevamente estos archivos indicando que
estos archivos tienen la extensión “.o”.
Si tenemos los archivos: main.c f1.c ...... fn.c
Entonces podemos compilar estos archivos con la siguiente línea de
comandos: gcc -o main main.c f1.c ....... fn.c
Y si los archivos fi.c y fj.c ya fueron previamente compilados, podemos
compilar todo nuevamente así: gcc -o main main.c f1.c ... fi.o ... fj.o ... fn.c
14. Compilar archivos con la utilería
make
La programación make es directa, basta con escribir una línea de comandos
en un archivo de texto con ciertas reglas en las que se indique la forma en que
se deben compilar los archivos.
Debe crearse un archivo con nombre Makefile y en este mismo directorio
escribir el comando make desde consola para así ejecutarlo. De este modo las
cosas que hayas indicado en el archivo se ejecutarán por el sistema operativo.
Los archivos make están compuestos de:
-Dependencias: lado_izquierdo:lado_derecho(el lado izquierdo nombra el
nuevo destino o tarjet mientras que el lado derecho nombra los archivos de los
que depende el nuevo)
15. Creación de un archivo make
El siguiente es un ejemplo
de archivo make:
prog: prog.o f1.o f2.o
gcc -o prog prog.o f1.o f2.o -lm ...
prog.o: cabecera.h prog.c
gcc -c prog.c
f1.o: cabecera.h f1.c
gcc -c f1.c
f2.o: ....
...
La utilería make lo interpretará de la siguiente forma:
1. prog depende de tres archivos: prog.o, f1.o y f2.o. Si cualquiera
de los archivos objeto ha cambiado desde la última
compilación los archivos deben ser religados.
2. prog.o depende de 2 archivos, si estos han cambiado prog.o
deberá ser recompilado. Lo mismo sucede con f1.o y f2.o.
Los últimos 3 comandos en makefile son llamados reglas explícitas
-- ya que los archivos en los comandos son listados por nombre.
16. Creación de un archivo make
Se pueden usar reglas implícitas en makefile para generalizar reglas y hacer más compacta la escritura.
Si se tiene:
f1.o: f1.c
gcc -c f1.c
f2.o: f2.c
gcc -c f2.c
se puede generalizar a:
.c.o: gcc -c $<
Lo cual se lee como .ext_fuente.ext_destino: comando donde $< es una forma breve para indicar los archivos que
tienen la extensión .c
Se pueden insertar comentarios en un Makefile usando el símbolo #, en donde todos los caracteres que siguen a
# son ignorados.
17. Uso de macros con make
Se pueden definir macros para
que sean usadas por make:
Se definen en una
forma simple, por
ejemplo:
FUENTES = main.c f1.c f2.c
CFLAGS = -ggdb -C
LIBS = -lm
PROGRAMA = main
OBJETOS = (FUENTES: .c =
.o)
En donde (FUENTES: .c = .o) cambia la extensión .c de los fuentes por la extensión.o
Para referirse o usar una macro con make se debe hacer $(nomb_macro), por ejemplo:
$(PROGRAMA) : $(OBJETOS)
$(LINK.C) -o $@ $(OBJETOS) $(LIBS)
En el ejemplo mostrado se observa que:
● La línea que contiene $(PROGRAMA) : $(OBJETOS) genera una lista de dependencias y el destino.
● Se emplean macros internas como $@.
Existen varias macros internas a continuación se muestran algunas de ellas:
$*
Parte del nombre del archivo de la dependencia actual sin el sufijo.
$@
Nombre completo del destino actual.
$
Archivo .c del destino
Un ejemplo de un makefile para el programa modular discutido previamente se muestra a continuación:
18. Uso de macros con make
#
# Makefile
#
FUENTES.c=main.c EscribirMiCadena.c
INCLUDES=
CFLAGS=
SLIBS=
PROGRAMA=main
OBJETOS=$(FUENTES.c:.c=.o)
# Destino (target) especial (inicia con .)
.KEEP_STATE:
debug := CFLAGS=-ggdb
all debug: $(PROGRAMA)
$(PROGRAMA): $(INCLUDES) $(OBJETOS)
$(LINK.c) -o $@ $(OBJETOS) $(SLIBS)
clean:
rm -f $(PROGRAMA) $(OBJETOS)