30.06.2015 Views

Programmazione modulare in C

Programmazione modulare in C

Programmazione modulare in C

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

<strong>Programmazione</strong> <strong>modulare</strong> nel<br />

l<strong>in</strong>guaggio C<br />

Paolo Bernardi<br />

07EIPCH<br />

AA 2008/09<br />

Ing. Paolo Bernardi


Introduzione<br />

– Non è possibile creare programmi di elevata<br />

complessità lavorando con un unico file sorgente<br />

• Lentezza di ricompilazione<br />

• Difficile riuso di procedure<br />

• Impossibile collaborare tra più programmatori<br />

• Difficile tener traccia delle modifiche<br />

– Occorre realizzare programmi distribuiti su più file<br />

sorgenti<br />

– Chiameremo tali programmi progetti multi-file o,<br />

più semplicemente progetti.<br />

2<br />

Ing. Paolo Bernardi


Compilazione e L<strong>in</strong>k<br />

.c<br />

Sorgente<br />

C<br />

Sorgente<br />

C<br />

Sorgente<br />

C<br />

Sorgente<br />

Assembler<br />

Compilatore Compilatore Compilatore<br />

Assemblatore<br />

.obj<br />

Codice<br />

oggetto<br />

Codice<br />

oggetto<br />

Codice<br />

oggetto<br />

Codice<br />

oggetto<br />

.exe<br />

Codice<br />

eseguibile<br />

L<strong>in</strong>ker<br />

Libreria<br />

Libreria<br />

.lib<br />

3<br />

Ing. Paolo Bernardi


Struttura del compilatore<br />

Sorgente C<br />

Analisi lessicale<br />

Analisi s<strong>in</strong>tattica<br />

Analisi semantica<br />

Generazione codice<br />

<strong>in</strong>dipendente HW<br />

Ottimizzazione<br />

Generazione codice b<strong>in</strong>ario<br />

Ottimizzazione<br />

Codice<br />

oggetto<br />

4<br />

Ing. Paolo Bernardi


Modulo di Codice oggetto<br />

– Contiene il codice b<strong>in</strong>ario corrispondente ad un<br />

modulo C<br />

– Contiene dei riferimenti esterni a funzioni e<br />

variabili dichiarate <strong>in</strong> altri moduli<br />

– Contiene funzioni e variabili utilizzabili da altri<br />

moduli<br />

– Uno ed un solo modulo nell’<strong>in</strong>tero progetto<br />

contiene il programma o funzione pr<strong>in</strong>cipale<br />

• <strong>in</strong>t ma<strong>in</strong>(void){…};<br />

5<br />

Ing. Paolo Bernardi


Modulo oggetto<br />

Funzioni usate dal<br />

modulo ma def<strong>in</strong>ite<br />

altrove<br />

strcmp<br />

strcpy<br />

6<br />

stdout<br />

Variabili usate dal<br />

modulo ma def<strong>in</strong>ite<br />

altrove<br />

sort.c<br />

sort.obj<br />

Codice<br />

b<strong>in</strong>ario<br />

Funzioni def<strong>in</strong>ite nel<br />

modulo, richiamabili<br />

anche dall’esterno<br />

<strong>in</strong>ssort<br />

cntsort<br />

scambi<br />

Variabili def<strong>in</strong>ite nel<br />

modulo, utilizzabili<br />

anche dall’esterno<br />

Ing. Paolo Bernardi


L<strong>in</strong>ker<br />

Codice<br />

oggetto<br />

Codice<br />

oggetto<br />

Codice<br />

oggetto<br />

Codice<br />

oggetto<br />

Codice<br />

oggetto<br />

7<br />

Ing. Paolo Bernardi


Modularità<br />

• Ciascun modulo <strong>in</strong> C:<br />

– Def<strong>in</strong>isce alcune funzioni “private”<br />

– Def<strong>in</strong>isce alcune funzioni “pubbliche”<br />

– Def<strong>in</strong>isce alcune variabili “private”<br />

– Def<strong>in</strong>isce alcune variabili “pubbliche”<br />

– Chiama alcune funzioni “esterne”<br />

– Usa alcune variabili “esterne”.<br />

8<br />

Ing. Paolo Bernardi


Chiamata di funzioni (I)<br />

void InsertionSort(<strong>in</strong>t A[], <strong>in</strong>t n) ;<br />

Funzione<br />

pubblica<br />

void InsertionSort(<strong>in</strong>t A[], <strong>in</strong>t n)<br />

{<br />

<strong>in</strong>t i, j, key ;<br />

/* … */<br />

libreria.c<br />

9<br />

extern void InsertionSort(<strong>in</strong>t A[], <strong>in</strong>t n) ;<br />

/* … */<br />

<strong>in</strong>t ma<strong>in</strong>(void)<br />

{ <strong>in</strong>t v[10] ;<br />

/* … */<br />

InsertionSort(v, 10) ;<br />

client.c<br />

/* … */<br />

Ing. Paolo Bernardi


Chiamata di funzioni (II)<br />

– Il modulo che esporta una funzione non deve fare<br />

nulla di particolare<br />

• <strong>in</strong> C, tutte le funzioni sono pubbliche cioè hanno classe<br />

di memorizzazione automatica<br />

• tranne nei casi <strong>in</strong> cui la loro dichiarazione sia preceduta<br />

dalla parola chiave static (funzioni private)<br />

– <strong>in</strong>vocabili esclusivamente dal modulo che le def<strong>in</strong>isce<br />

– Il modulo che utilizza la funzione deve dichiararne<br />

il prototipo (con la parola chiave extern)<br />

– Il l<strong>in</strong>ker farà il collegamento.<br />

10<br />

Ing. Paolo Bernardi


Funzioni private<br />

– Nel caso <strong>in</strong> cui un modulo def<strong>in</strong>isca delle funzioni<br />

che NON vuole esportare, nella def<strong>in</strong>izione (non<br />

nel prototipo) deve comparire la parola chiave<br />

static.<br />

void InsertionSort(<strong>in</strong>t A[], <strong>in</strong>t n) ;<br />

void CancellaVettore(<strong>in</strong>t A[], <strong>in</strong>t n) ;<br />

void InsertionSort(<strong>in</strong>t A[], <strong>in</strong>t n)<br />

{ . . . }<br />

static void CancellaVettore(<strong>in</strong>t A[], <strong>in</strong>t n)<br />

{ . . . }<br />

11<br />

Ing. Paolo Bernardi


Variabili globali (I)<br />

<strong>in</strong>t n_elem ; client.c<br />

double vett[MAX] ;<br />

static <strong>in</strong>t temp ;<br />

extern <strong>in</strong>t n_elem ; libreria.c<br />

extern double vett[MAX] ;<br />

/* … */<br />

{ for(i=0; i


Variabili globali (II)<br />

– Il modulo che esporta una variabile globale non<br />

deve fare nulla di particolare: <strong>in</strong> C, tutte le variabili<br />

globali sono pubbliche (per default)<br />

– Il modulo che utilizza la variabile deve ri-def<strong>in</strong>irla<br />

con la parola chiave extern<br />

– Se non si vuole esportare una variabile occorre<br />

def<strong>in</strong>irla con la parola chiave static<br />

– Le variabili locali (alle procedure) non possono<br />

essere condivise.<br />

13<br />

Ing. Paolo Bernardi


Problemi<br />

– Le due dichiarazioni (nel modulo che esporta e<br />

nei moduli che usano la funzione/variabile)<br />

devono co<strong>in</strong>cidere al 100%<br />

<strong>in</strong>t f( <strong>in</strong>t x ) ;<br />

Errore!<br />

extern <strong>in</strong>t f( double x );<br />

14<br />

<strong>in</strong>t f(<strong>in</strong>t x)<br />

{ . . . }<br />

libreria.c<br />

<strong>in</strong>t ma<strong>in</strong>(void)<br />

{ . . .<br />

y = f ( z ) ;<br />

. . .}<br />

client.c<br />

Ing. Paolo Bernardi


Il ruolo degli header file<br />

– Si possono utilizzare degli header file (file .h) per<br />

raccogliere le def<strong>in</strong>izioni extern di funzioni e<br />

variabili pubbliche<br />

– Il creatore del modulo che esporta le funzioni o<br />

variabili crea un file .h<br />

– Tutti i moduli che usano tali risorse esportate<br />

<strong>in</strong>cludono i file .h (#<strong>in</strong>clude).<br />

15<br />

Ing. Paolo Bernardi


Esempio di header file (I)<br />

void InsertionSort(<strong>in</strong>t A[], <strong>in</strong>t n) ;<br />

extern <strong>in</strong>t n_elem ;<br />

extern double vett[MAX] ; sort.h<br />

#<strong>in</strong>clude "sort.h" /* per controllo coerenza */<br />

<strong>in</strong>t n_elem ;<br />

double vett[MAX] ;<br />

sort.c<br />

static <strong>in</strong>t temp ;<br />

void InsertionSort(<strong>in</strong>t A[], <strong>in</strong>t n)<br />

{ . . . }<br />

static void CancellaVettore(<strong>in</strong>t A[], <strong>in</strong>t n)<br />

{ . . . }<br />

16<br />

Ing. Paolo Bernardi


Esempio di header file (II)<br />

void InsertionSort(<strong>in</strong>t A[], <strong>in</strong>t n) ;<br />

extern <strong>in</strong>t n_elem ;<br />

extern double vett[MAX] ; sort.h<br />

#<strong>in</strong>clude "sort.h" /* per importare dichiarazioni */<br />

<strong>in</strong>t ma<strong>in</strong>(void)<br />

{ <strong>in</strong>t v[10] ;<br />

/* … */<br />

client.c<br />

InsertionSort(v, 10) ;<br />

/* … */<br />

for(i=0; i


Note<br />

– Ciascun modulo solitamente esporta alcune<br />

funzioni o variabili, e ne importa altre<br />

– È sempre bene che ciascun modulo <strong>in</strong>cluda<br />

anche il proprio header file<br />

– Conviene limitare al m<strong>in</strong>imo il numero di variabili<br />

condivise<br />

– Includere anche le #def<strong>in</strong>e nei file .h<br />

– È buona norma raccogliere tra loro gruppi di<br />

moduli correlati per funzionalità<br />

• possono condividere l’header file.<br />

18<br />

Ing. Paolo Bernardi


Inclusione multipla di librerie<br />

• L’uso delle librerie può orig<strong>in</strong>are problemi <strong>in</strong><br />

fase di compilazione<br />

• Se 2 moduli differenti di uno stesso progetto<br />

<strong>in</strong>cludono la stessa libreria, il compilatore<br />

– rileverà variabili e funzioni def<strong>in</strong>ite 2 volte<br />

– <strong>in</strong>terromperà il processo di compilazione del<br />

progetto.<br />

19<br />

Ing. Paolo Bernardi


Inclusione multipla di librerie (cont.)<br />

20<br />

• Utilizzo di direttive per il compilatore<br />

• Alla prima <strong>in</strong>clusione la variabile di compilazione MNEMONICO<br />

non è ancora stata def<strong>in</strong>ita, qu<strong>in</strong>di il file viene l<strong>in</strong>kato<br />

regolarmente<br />

• Alla seconda, essendo MNEMONICO già stato def<strong>in</strong>ito, il<br />

contenuto del file non viene ricaricato.<br />

#ifndef MEMONICO<br />

#def<strong>in</strong>e MEMONICO<br />

void InsertionSort(<strong>in</strong>t A[], <strong>in</strong>t n) ;<br />

extern <strong>in</strong>t n_elem ;<br />

extern double vett[MAX] ;<br />

#endif<br />

Identificatore univoco all’<strong>in</strong>terno<br />

del progetto, ovvero 1<br />

MNEMONICO differente per file<br />

sort.h<br />

Ing. Paolo Bernardi


Filosofia della<br />

programmazione multi-file<br />

21<br />

• Il l<strong>in</strong>guaggio C mette a disposizione del<br />

programmatore pochi semplici strumenti che,<br />

accompagnati ad una opportuna e necessaria<br />

discipl<strong>in</strong>a di programmazione, consentono di gestire<br />

<strong>in</strong> maniera ottimale progetti software di grandi<br />

dimensioni [Luca Durante]<br />

• Il kernel di L<strong>in</strong>ux, circa 100 MB di sorgente,<br />

suddiviso <strong>in</strong> circa 8000 di file sorgenti, è scritto <strong>in</strong><br />

massima parte <strong>in</strong> C (e <strong>in</strong> assembler la restante<br />

parte) da cent<strong>in</strong>aia di programmatori sparsi per il<br />

mondo, che spesso non si sono neppure mai<br />

<strong>in</strong>contrati.<br />

Ing. Paolo Bernardi


Sviluppo di grandi progetti<br />

• Necessita di organizzazione e s<strong>in</strong>cronismo<br />

• Def<strong>in</strong>izione delle <strong>in</strong>terfacce, cioè del<br />

contenuto degli header file<br />

– Per ciascuna funzione sono specificate le<br />

funzionalità<br />

• Ripartizione delle risorse<br />

– 1 modulo di libreria = 1 programmatore.<br />

22<br />

Ing. Paolo Bernardi


Sviluppo di grandi progetti (cont.)<br />

23<br />

• Uso dei cosiddetti repository<br />

– 1 versione gold del progetto (obbligatoriamente<br />

funzionante) memorizzata su un server remoto<br />

– N versioni locali a disposizione dei s<strong>in</strong>goli programmatori<br />

per valutare le soluzioni sul modulo di propria competenza<br />

• Il programmatore impegnato nello sviluppo proprio<br />

modulo<br />

– Scarica <strong>in</strong> locale l’<strong>in</strong>tero progetto gold (update)<br />

– Lo modifica e valuta l’efficacia del suo <strong>in</strong>tervento<br />

– Se soddisfacente, lo carica sul server all’<strong>in</strong>terno del<br />

progetto gold (commit)<br />

• È mantenuta la “storia” dei commit.<br />

Ing. Paolo Bernardi


Sviluppo di grandi progetti (cont.)<br />

Implementazione<br />

LOCAL<br />

LOCAL<br />

Update<br />

Commit<br />

Update<br />

Commit<br />

24<br />

Def<strong>in</strong>izione delle<br />

specifiche<br />

GOLD<br />

Ing. Paolo Bernardi

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!