Dove scrivere le funzioni all'interno del nostro codice sorgente

Negli esempi dei post precedenti avrete notato che la definizione delle funzioni è stata scritta sempre prima del blocco main().

Il motivo è che, per richiamare una funzione, questa dev'essere stata prima definita.
Fare il contrario sarebbe un po' come utilizzare una variabile ancora prima di averla dichiarata:

var1 = var2 + var3; //Cosa?? le tre variabili non sono state ancora dichiarate!

//...codice...

int var1, var2, var3;

Quindi basta scrivere la definizione di una funzione prima del main? Non sempre.
Infatti una funzione può essere richiamata anche all'interno di altre funzioni, e capita che due funzioni si chiamino tra loro:
void funzione1() //DEFINIZIONE DI funzione1
{
//...codice...
funzione2(); //RICHIAMO funzione2
//...codice...
}

void funzione2() //DEFINIZIONE DI funzione2
{
//...codice...
funzione1(); //RICHIAMO funzione1
//...codice...
}
Come potete vedere le funzioni si richiamano a vicenda.
funzione2() richiama funzione1() all'interno del suo codice; questo è corretto perché funzione1() è già stata definita prima, essendo sopra di lei.
funzione1() richiama funzione2(), e questo è errato, perché funzione2() non è stata ancora definita, essendo sotto.

Non possiamo sostituire l'ordine delle due definizioni perché in quel caso sarebbe funzione2() a richiamare una funzione non ancora definita.

Nei programmi di una certa grandezza questo succede praticamente sempre, e comunque i programmatori non possono controllare caso per caso quando succede, perciò è necessaria una soluzione che funzioni sempre.

Questo problema viene risolto grazie all'utilizzo dei prototipi delle funzioni:

void funzione1(); //PROTOTIPO DI funzione1
void funzione2(); //PROTOTIPO DI funzione2

void funzione1() //DEFINIZIONE DI funzione1

{
//...codice...
funzione2(); //RICHIAMO funzione2
//...codice...
}

void funzione2() //DEFINIZIONE DI funzione2
{
//...codice...
funzione1(); //RICHIAMO funzione1
//...codice...
}
I prototipi precedono entrambe le definizioni, così in entrambi i casi il compilatore è in grado di riconoscere la funzione richiamata, anche se non è stata ancora definita.
Ad esempio funzione1() richiama al suo interno funzione2(), che non è stata ancora definita; ma il prototipo della funzione all'inizio del codice sorgente fa sì che il compilatore conosca già la funzione, perché prima di giungere al punto in cui viene richiamata funzione2() all'interno di funzione1(), ha già incontrato il prototipo di funzione2() e quindi conosce già il nome della funzione, il tipo restituito e il tipo dei parametri.

La forma generale di un prototipo di funzione è:

tipo nome_funzione(tipo nome_parametro1, tipo nome_parametro2);

E' anche possibile tralasciare il nome del parametro, l'importante è che sia specificato il tipo, ad esempio:

int somma(int, int);

Più avanti, quando impareremo a suddividere i nostri progetti in più files, vedremo che le funzioni ed i rispettivi prototipi vanno in files differenti, e al momento dell'inclusione sarà sufficiente includere i file contenenti i prototipi.

Per adesso ci limiteremo a scrivere i prototipi prima del main(), e le definizioni delle funzioni dopo il main().

Nessun commento:

Posta un commento