E' considerata buona tecnica di programmazione usare i prototipi delle funzioni per tutte le funzioni di un programma. Un prototipo dichiara il nome della funzione, i suoi parametri e il tipo di dato che viene restituito; il tutto prima della definizione della funzione.
Per capire perchè i prototipi delle funzioni sono utili, digitate il seguente codice ed eseguitelo:
#include <stdio.h> void main() { printf("%d\n",add(3)); } int add(int i, int j) { return i+j; }
Questo codice è correttamente compilato da molti compilatori senza che vi siano warning (avvertimenti) anche se la funzione add si aspetta di ricevere in ingresso due parametri ma ne riceve solo uno. Funziona perchè molti compilatori C non controllano il matching esatto fra il numero di parametri effettivamente passati e quelli dichiarati. Si può quindi perdere molto tempo nel debug del codice quando l'errore sta semplicemente nell'aver passato il numero non corretto di parametri. Quindi, il codice precedente viene compilato senza errori ma produce un risultato sbagliato.
Per risolvere questo problema, il C permette che il prototipo della funzione sia indicato all'inizio (o anche in qualsiasi punto) del programma. Se si fa così, il compilatore effettua il controllo fra numero di parametri passati e numero di parametri indicati nel prototipo. Provate quindi a compilare il seguente codice:
#include <stdio.h> int add (int,int); /* function prototype for add */ void main() { printf("%d\n",add(3)); } int add(int i, int j) { return i+j; }
Il prototipo provoca la generazione di un errore inerentemente la funzione printf. Inserire quindi il prototipo delle funzioni che si andranno ad utilizzare permetterà di risparmiare notevole tempo in fase di debug. Inoltre, così si risolve anche il problema che sorge quando si compila in presenza di funzioni utilizzate prima che siano state definite. Per esempio, il codice seguente non verrà compilato correttamente:
#include <stdio.h> void main() { printf("%d\n",add(3)); } float add(int i, int j) { return i+j; }
Ci si potrebbe chiedere perchè questo codice viene compilato quando si aggiunge di restituire un intero ma non quando restituisce un float? Perchè i vecchi compilatori C utilizzano un intero come default da restituire. Usare un prototipo risolve il problema. I compilatori vecchia maniera non-ANSI permettono l'uso di prototipi di funzione ma la lista di parametri nel prototipo deve essere vuota. Inoltre, i compilatori vecchia maniera non controllano il numero di parametri.
Approfondimenti ed esercizi
• ritornate al problema dell'algoritmo bubble sort per creare una funzione bubble_sort()
• creare una funzione che permetta di ottenere l'input dall'utente e riscrivere i programmi in modo da usare questa nuova funzione piuttosto che chiedere l'input all'utente ogni volta nel programma.