Ferramentas do usuário

Ferramentas do site


prog2:organizacao_de_codigo

Organização do código

À medida em que um software cresce em tamanho e funcionalidades, seu código-fonte deve ser organizado corretamente para facilitar sua compreensão, manutenção e evolução. É importante quebrar o código-fonte em arquivos separados, dividindo-o de acordo com os módulos e/ou funcionalidades do sistema.

Ao dividir o código-fonte em arquivos separados, alguns cuidados devem ser tomados:

  • Agrupe as funções e definições de dados correlatos em um mesmo arquivo .c;
  • Coloque os protótipos das funções públicas e as definições de dados necessárias às mesmas em um arquivo de cabeçalho .h (com o mesmo nome do arquivo .c correspondente), a ser incluso pelos arquivos que usarem essas funções;
  • Somente efetue inclusões (#include) de arquivos de cabeçalho (.h).

Considerando um arquivo abobrinha.c contendo várias funções e definições de estruturas de dados, imagine o arquivo de cabeçalho abobrinha.h como a definição da interface a ser usada por outros arquivos C para usar as funcionalidades implementadas em abobrinha.c.

Maldições imperdoáveis :-X:

  • fazer inclusão de arquivos de código (#include “arquivo.c”)
  • colocar código real (for, if, while, …) em arquivos de cabeçalho (.h)

Exemplo

O exemplo didático a seguir implementa um conjunto de funções que permitem definir e operar sobre números complexos.

O arquivo principal (neste exemplo, main.c) deve incluir todos os arquivos de cabeçalho necessários para sua compilação e também deve definir a função main:

main.c
#include "complex.h"
 
int main()
{
  complex_t a, b, c ;
 
  complex_define (&a, 10, 17) ;
  complex_define (&b, -2, 4) ;
  complex_sum (&c, a, b);
  ...
}

Como o arquivo main.c provavelmente não define funções (ou estruturas, tipos, etc) que serão usadas em outros programas, não é necessário criar um arquivo main.h.

Por sua vez, o arquivo de cabeçalho complex.h deve declarar somente informações públicas: tipos de dados e protótipos de funções que devem ser conhecidas por quem irá utilizar as funcionalidades providas por complex.c:

complex.h
#ifndef __COMPLEX__
#define __COMPLEX__
 
typedef struct {
  float r,i;
} complex_t ;
 
void complex_define (complex_t *v, float r, float i) ;
...
 
#endif

Deve-se observar o uso das macros de pré-compilação #ifdef e #define, para evitar a repetição das definições, caso o mesmo arquivo de cabeçalho seja incluído múltiplas vezes em diferentes locais do código.

O arquivo correspondente complex.c conterá então as informações privadas do módulo: estruturas de dados internas, variáveis globais e implementações das funções. Esse arquivo deve incluir todos os cabeçalhos necessários à implementação das funções.

complex.c
#include <math.h>
#include "complex.h"
 
// internal function, used only in this file
void convert_polar_rect (float r, float a, float *x, float *y)
{
  // implementation of the function
  ...
}
 
// function "exported" through complex.h
void complex_define (complex_t *v, float r, float i) 
{
  // implementation of the function
  ...
}
 
...

Em resumo:

  • complex.c: implementação das funções de manipulação de números complexos.
  • complex.h: interface (protótipos) das funções definidas em complex.c.
  • main.c: programa principal, que usa as funções descritas em complex.h e implementadas em complex.c.

Para compilar:

cc -Wall main.c complex.c -o main -lm

O arquivo complex.c também pode ser compilado separadamente, gerando um arquivo-objeto complex.o que poderá ser ligado ao arquivo main.o posteriormente. Essa organização torna mais simples a construção de bibliotecas e a distribuição de código binário para incorporação em outros projetos (reuso de código). Além disso, essa estruturação agiliza a compilação de grandes projetos, através do sistema Make.

Um outro aspecto importante da organização do código é o uso de declarações extern para variáveis globais usadas em vários arquivos de código-fonte. Esta página contém uma excelente explicação sobre o uso correto da declaração extern.

prog2/organizacao_de_codigo.txt · Última modificação: 2019/04/09 13:35 por maziero