- I puntatori a funzione in C -
|
|||
COSA SERVE PER QUESTO TUTORIAL | |||
Download | Chiedi sul FORUM | Glossario | cognizioni basiche di C e dell'uso dei puntatori | ||
Cosa sono e come si usano i puntatori a funzione | |||
PUNTATORI A FUNZIONI COME VARIABILI Come definire puntatori a funzione con typedef.
Chiunque abbia una minima esperienza di C conosce i puntatori e il loro
utilizzo, ma spesso vengono dimenticati i puntatori a funzione,
soprattutto per via della loro complessità sintattica, vediamo cosa
sono, a cosa servono e come usarli. #include <stdio.h> int main(int argc, char *argv[]) { printf("%p\n", main); return 0; } Questo codice produrrà un numero che sarà l'indirizzo della funzione main stessa. Si badi che se dopo main si fossero messe le parentesi sarebbe stata una chiamata alla funzione, mentre invece mettendo solo il nome si intende passare come parametro la funzione stessa e quindi il suo indirizzo. Infatti sarebbe stato equivalente scrivere: printf("%p\n", &main); Tuttavia non è possibile scrivere sull'area di memoria in condizioni normali e pertanto il seguente codice porterà ad un crash: #include <stdio.h> int main(int argc, char *argv[]) { /* Punta ad una funzione e non ad un intero in realtà */ int *indirizzoMain = (int*) main; printf("%p\n", indirizzoMain); indirizzoMain[0] = 312; return 0; } Ora abbiamo memorizzato il puntatore alla funzione come un puntatore ad un intero, ma questo è profondamente errato, infatti l'area di memoria contiene una funzione e non un numero intero, pertanto ci sono altri metodi per definire il tipo di un puntatore a funzione. Vediamo un caso semplificato: #include <stdio.h> int somma(int a, int b) { return a + b; } int main(int argc, char *argv[]) { int (*funzioneSomma)(int, int); funzioneSomma = somma; printf("%p\n", funzioneSomma); return 0; }
In questo caso l'indirizzo che verrà stampato sarà quello della funzione
somma, ma vediamo come abbiamo dichiarato il nostro puntatore a
funzione, funzioneSomma: esso è del tutto simile al prototipo (o
dichiarazione) della funzione somma, a parte per il fatto che al posto
del nome della funzione abbiamo racchiuso tra parentesi il nome della variabile che
intendiamo dichiarare, preceduto da un asterisco, ad indicare che è un
puntatore. Si noti che i nomi degli argomenti
possono essere tranquillamente omessi, in quanto ciò che stiamo dicendo
al compilatore è: dichiara un variabile di tipo puntatore ad una
funzione che riceve come parametri due interi e ne restituisce un altro.
Per il resto possiamo usare il nostro puntatore funzioneSomma come un
qualunque altro puntatore. #include <stdio.h> int somma(int a, int b) { return a + b; } int differenza(int a, int b) { return b - a; } typedef int (*operatoreBinario)(int, int); int main(int argc, char *argv[]) { operatoreBinario operatore; operatore = somma; printf("%p\n", operatore); operatore = differenza; printf("%p\n", operatore); return 0; }
Come si può vedere il typedef funziona alla stessa maniera della
dichiarazione della variabile. int main(int argc, char *argv[]) { operatoreBinario operatore; int a = 3, b = 4; operatore = somma; printf("%p %d\n", operatore, operatore(a, b)); operatore = differenza; printf("%p %d\n", operatore, (*operatore)(a, b)); return 0; }
Si noti che la prima sintassi è equivalente alla seconda ma abbreviata. #include <stdio.h> #include <stdlib.h> void *funzione1(char carattere) { return (void*) NULL; } typedef void* (*puntatoreFunzione1)(char); char *funzione2(int *puntatoreAIntero) { return (char *) NULL; } typedef char* (*puntatoreFunzione2)(int *); void****** funzione3(int parametro, ...) { return NULL; } typedef void****** (*puntatoreFunzione3)(int, ...); RESTITUIRE E PASSARE COME PARAMETRO UN
PUNTATORE A FUNZIONE Per passare come argomento o far restituire ad una funzione un puntatore a funzione ci sono due vie: la prima semplice e la seconda molto meno leggibile. La prima consiste semplicemente nel servirsi del typedef: typedef int (*operatoreBinario)(int, int); operatoreBinario scegli(char simbolo) { switch (simbolo) { case '+': return somma; break; case '-': return differenza; break; default: return somma; } } La seconda invece è come segue: int (*scegli(char simbolo))(int, int) { switch (simbolo) { case '+': return somma; break; case '-': return differenza; break; default: return somma; } } Stesso discorso vale per passare come parametro un puntatore a funzione: typedef int (*operatoreBinario)(int, int); /* int eseguiOperazione(int (*operazione)(int, int), int a, int b) { */ int eseguiOperazione(operatoreBinario operazione, int a, int b) { return operazione(a, b); }
|
|||
<< INDIETRO | by VeNoM00 |