Abbiamo spiegato le basi della programmazione in C, ma sempre limitandoci a programmi di dimensioni medio/piccole; è utile, quindi, affrontare gli aspetti teorici e pratici dello sviluppo di programmi di una certa dimensione, questo perché un progetto con applicazioni reali usualmente raggiunge grandi dimensioni.
In questi casi è consigliabile dividere i programmi in moduli, che dovrebbero stare in file sorgenti separati (quindi ogni file conterrà uno o più funzioni), mentre l'istruzione main dovrà essere in un solo file (generalmente main.c). Alla fine questi moduli interagiranno tra loro semplicemente includendoli in fase di compilazione, con l'ovvio vantaggio anche di riusabilità per altri programmi.
Tutto ciò viene fatto, con gli strumenti adeguati, per ovvie ragioni:
- I moduli verranno divisi in gruppi di funzioni comuni
- è possibile compilare separatamente ogni modulo e poi linkarlo nei moduli compilati
- Usando utility come make, si possono mantenere abbastanza facilmente grossi sistemi
Utilizzo dei file header
Utilizzando un approccio modulare, dovremo includere in ogni modulo la definizione delle variabili, i prototipi di funzioni ed i comandi per il preprocessore C, etc. Questo potrebbe causare problemi di mantenimento del software, così è consigliabile centralizzare queste definizioni all'interno di un file (o più di uno) e condividere, poi, le informazioni con gli altri file. Tali file vengono generalmente definiti "header file" (file di intestazione) e devono avere estensione (un suffiso) .h
.
Generalmente includiamo i file header delle librerie standard, come ad esempio <stdio.h>
o <stdlib.h>
, mettendoli, appunto tra il simbolo di minore (<
) e di maggiore (>
), questa è la convenzione usata per includere gli header di sistema (di cui il compilatore conosce il percorso completo);
Includere header file di sistema
#include
Per includere invece, all'interno di un file .c
, un file header che risiede nella medesima directory, dobbiamo usare le virgolette (""
). Ad esempio, per includere un file di nome mia_intestazione.h
, basta scrivere all'interno del file:
#include "mia_intestazione.h"
Per programmi di moderate dimensioni è meglio avere due o più file header che condividono le definizioni di più di un modulo ciascuno. Il problema sorge quando abbiamo delle variabili globali in un modulo e vogliamo che vengano riconosciute anche negli altri.
Generalmente le variabili esterne e le funzioni devono avere visibilità globale. Quindi per le funzioni vengono usati i prototipi di funzioni, mentre possiamo usare il prefisso "extern" per le variabili globali che, in questo modo, vengono dichiarate ma non definite (cioè non viene allocata memoria per la variabile), saranno definite, poi, una ed una sola volta all'interno di un modulo che comporrà il programma; per questo possiamo avere tantissime dichiarazioni esterne, ma una sola definizione della variabile.