quarta-feira, 14 de julho de 2021

Um pouco de a, b, c e main da programação modular.

Este é um mais um caso no qual uma explicação para uma pessoa nas redes sociais fica tão boa que vira um artigo no blog. O texto vai abaixo:
 
Um header, um arquivo .h, NUNCA deverá gerar código ou dados. Pode definir variáveis, mas somente como extern. Pode ter protótipos de funções, definição de tipos, enum, macros, mas NUNCA deve definir uma variável alocando espaço em memória ou ter o código de uma função.
 
Os .c e .cpp são onde estão as definições de variáveis e código.
 
Digamos que vamos fazer um programa que é dividido em partes. A parte "a" que é usada pela "b" e "c", e a parte "main" seria o programa principal e depende diretamente das partes "b" e "c".
 
Então teríamos os arquivos a.h, a.c, b.h, b.c, c.h, c.c e main.c.
 
a.c
 
Define algumas funções e variáveis que também serão vistas por outros módulos. Inclui alguns headers padrão entre <> e a.h entre aspas.
 
a.h
 
Contém os protótipos das funções escritas em a.c, e em extern as variáveis de a.c que precisam ser vistas por outros módulos.
 
b.c
 
Define algumas funções e variáveis que também serão vistas por outros módulos. Inclui alguns headers padrão entre <>, e a.h e b.h entre aspas.
 
b.h
 
Contém os protótipos das funções escritas em b.c, e em extern as variáveis de b.c que precisam ser vistas por outros módulos.
 
c.c
 
Define algumas funções e variáveis que também serão vistas por outros módulos. Inclui alguns headers padrão entre <>, e a.h e c.h entre aspas.
 
c.h
 
Contém os protótipos das funções escritas em c.c, e em extern as variáveis de c.c que precisam ser vistas por outros módulos.
 
main.c
 
Já que este depende diretamente somente de b.c e c.c, então inclui alguns headers padrão entre <>, e b.h e c.h entre aspas. A dependência do módulo "a" se faz indiretamente.
 
O Makefile deste projeto fica aproximadamente assim.
 
programa: main.c b.o c.o
    cc -s -O3 -o programa main.c a.o b.o c.o
 
a.o: a.c a.h
    cc -O3 -c a.c
 
b.o: b.h b.c a.o
    cc -O3 -c b.c
 
c.o: c.h c.c a.o
    cc -O3 -c c.c
 
E assim só os módulos necessários é que serão compilados. Se editar o main.c, só ele será compilado. Se editar o a.h ou o a.c, tudo será compilado, pois tudo depende diretamente ou indiretamente deles. Se editar b.c ou b.h, só b.c e main.c serão compilados.
 
Acho que dá para fazer um Makefile mais detalhado, de modo que nem main.c seja compilado do zero se os headers não forem modificados.

Aqui já terminou o texto da rede social, mas tenho este texto falando que vale para ler, pois justamente é sobre como variáveis são alocadas em memória, sobre extern, e sobre funções e variáveis locais a módulos.