prof. Nunzio Brugaletta | Programmazione e linguaggio C |
Nel linguaggio C la maggior parte di quello che si usa è costituito da funzioni. Per poter simulare le procedure che non ritornano alcun valore è stato introdotto il tipo void. Il tipo void o tipo indefinito è utilizzato dal linguaggio C tutte le volte che il valore di ritorno di una funzione non deve essere preso in considerazione. In pratica nel linguaggio C le procedure sono funzioni che restituiscono un void.
La costruzione e l’uso di una funzione si possono sintetizzare in tre fasi:
La definizione della funzione cioè l’elenco delle operazioni svolte dalla funzione stessa. La definizione comincia specificando il tipo di valore ritornato, subito dopo viene specificato il nome scelto a piacere dal programmatore e seguente le regole della scelta del nome delle variabili, viene quindi specificato l’elenco dei parametri e infine le dichiarazioni locali e le istruzioni così come dallo schema seguente:
tipo-ritornato nome-funzione(dichiarazione parametri) { dichiarazioni ed istruzioni }
Le definizioni di funzioni possono essere scritte in qualsiasi punto del programma: verranno mandate in esecuzione soltanto in seguito alla chiamata e quindi non ha alcuna importanza il posto fisico dove sono allocate. È convenzione comune codificarle dopo il main. D’altra parte il main stesso non è altro che una funzione particolare che viene eseguita per prima. Il programma quando viene eseguito effettua una chiamata alla funzione main. Il tipo-ritornato non è specificato perché si sottintende int: quando non è specificato il tipo, il linguaggio C assume per default il tipo int sebbene, per motivi di comprensibilità, sia sempre opportuno dichiarare il tipo. In definitiva all’atto dell’esecuzione il programma effettua una chiamata alla funzione main, questa può restituire al chiamante (in questo caso il Sistema Operativo) un valore intero. Tale valore potrebbe per esempio essere utilizzato per stabilire l’azione da svolgere in relazione ad una terminazione anomala del programma.
Fra le istruzioni contenute nella definizione della funzione particolare importanza assume l’istruzione return utilizzata per ritornare al chiamante un valore. La sintassi dell’istruzione prevede di specificare dopo la parola chiave return un valore costante o una variabile compatibile con il tipo-ritornato dalla funzione. Es.
return 5; /* Ritorna al chiamante il valore 5 */ return a; /* Ritorna al chiamante il valore contenuto nella variabile a */
Non è importante che le definizioni di tutte le funzioni usate in un programma seguano l’ordine con cui sono chiamate sebbene, per motivi di chiarezza e leggibilità, è opportuno che sia così e che si segua l’ordine specificato prima. In ogni caso la funzione con il nome main viene eseguita per prima in qualunque posto sia messa e le funzioni vengono eseguite nell’ordine in cui sono chiamate.
Il prototipo della funzione. Si tratta in sintesi di ripetere all’inizio del programma, prima della definizione della funzione main, le dichiarazioni delle funzioni definite dopo. Si riscrive in pratica quanto specificato nella prima riga della definizione della funzione.
I prototipi sono stati introdotti dallo standard ANSI per poter permettere al compilatore di effettuare un maggiore controllo sui tipi di parametri: conoscendoli in anticipo infatti, all’atto della chiamata che avviene a partire dalla funzione main (la prima eseguita), è possibile stabilire se i parametri passati sono congruenti con quelli attesi. È per questo motivo che, per la precisione, nel prototipo non è necessario dichiarare i nomi dei parametri, ma solo i tipi.
Nella costruzione di programmi complessi capita di utilizzare molte funzioni. In questo caso le funzioni sono raggruppate in librerie e i rispettivi prototipi sono raggruppati nei files di intestazione (header files). Gli header sono file di tipo testo che hanno estensione ".h". Si è avuto modo di utilizzare librerie di funzioni fin dall’inizio. Per esempio sia scanf che printf sono funzioni contenute in una libreria di sistema che viene inclusa, all’atto della compilazione, nel nostro programma. I prototipi di tali funzioni sono nello header stdio.h che, per tali motivi, viene incluso all’inizio del programma.
La chiamata della funzione. Consiste semplicemente nello specificare, laddove occorre utilizzare l’elaborazione fornita dalla funzione, il nome della funzione stessa accompagnato dall’elenco dei parametri passati. Il programma chiamante può utilizzare il valore restituito dalla funzione e in tal caso il nome della funzione figurerà, per esempio, in una espressione. Il chiamante può anche trascurare il valore restituito anche se non è di tipo void. Basta utilizzare la funzione senza assegnare il suo valore restituito. La funzione scanf, per esempio, restituisce un intero che indica quanti input sono stati effettuati, ma negli esempi fin qui trattati non si è mai utilizzato tale valore di ritorno. Ciò potrebbe per esempio essere utile per conoscere, prima di proseguire nell’elaborazione, se tutti gli input richiesti sono quelli che ci si aspettava:
... while(scanf("%d,%d",&a,&b)!=2); ...
L’istruzione specificata è un ciclo che controlla se il valore di ritorno della scanf è diverso da 2 (non ci sono stati due input validi) e in tal caso ripete l’input (il ciclo ha solo l’istruzione di controllo).
http://ennebi.solira.org | ennebi@solira.org |