Puntatore a funzione in C
-
Usa la notazione
void (*func)()
per definire il puntatore a funzione in C - Utilizzare la matrice di puntatori di funzione per implementare la funzione di programmazione generica di tipo
Questo articolo introdurrà come utilizzare un puntatore a funzione in C.
Usa la notazione void (*func)()
per definire il puntatore a funzione in C
I puntatori a funzione sono ancora un altro costrutto nella programmazione C che implementano funzionalità avanzate come chiamate dinamiche di funzioni, strutture che includono i propri metodi simili alla progettazione orientata agli oggetti, programmazione generica di tipo e così via. La notazione void (*func)(void)
dichiara il puntatore alla funzione void
che non accetta parametri. Sebbene assegniamo l’indirizzo della funzione printInt
, questo richiede un singolo argomento int
al puntatore alla funzione di tipo void (*func)(void)
nell’esempio seguente. Una volta definito il puntatore a funzione denominato func
, può essere chiamato con la solita notazione di chiamata di funzione func(arg)
o con l’operatore di dereferenziazione func(arg)
.
#include <stdio.h>
#include <stdlib.h>
void printInt(int x) { printf("printed from printInt: %d\n", x); }
int main() {
int input1 = 10233;
void (*func)(int) = printInt;
func(input1);
(*func)(input1);
exit(EXIT_SUCCESS);
}
Produzione:
printed from printInt: 10233
printed from printDouble: 11.234000
In alternativa, possiamo definire un nuovo alias di tipo di un puntatore a funzione usando typedef
per rendere il codice più leggibile. Notare che diversi tipi di funzioni necessitano di istruzioni typedef
separate. Nel seguente esempio di codice, definiamo un puntatore a una funzione void senza argomenti; tuttavia, entrambi gli indirizzi delle funzioni printInt
e printDouble
sono memorizzati nella variabile di tipo FuncPtr
. Si noti che l’indirizzo della funzione specifica può essere preso con l’operatore &
esplicito o con l’assegnazione implicita del nome della funzione stessa, come mostrato nel prossimo esempio.
#include <stdio.h>
#include <stdlib.h>
typedef void (*FuncPtr)();
void printInt(int x) { printf("printed from printInt: %d\n", x); }
void printDouble(double x) { printf("printed from printDouble: %f\n", x); }
int main() {
int input1 = 10233;
double input2 = 11.234;
FuncPtr func1 = printInt;
FuncPtr func2 = printDouble;
func1(input1);
func2(input2);
exit(EXIT_SUCCESS);
}
Produzione:
printed from printInt: 10233
printed from printDouble: 11.234000
Utilizzare la matrice di puntatori di funzione per implementare la funzione di programmazione generica di tipo
Come altri oggetti, si può definire un array di puntatori a funzione con la notazione tra parentesi []
. Questo array può essere utilizzato per scegliere e chiamare facilmente funzioni specifiche durante il runtime. Si noti che stiamo usando la parola chiave _Generic
, che è switch
come un’espressione che consente all’utente di scegliere il caso specifico in base alla valutazione del tipo dell’espressione di controllo. Di conseguenza, implementiamo il seguente esempio di codice, dove la corrispondente funzione print
viene chiamata in base al tipo di variabile passata nella condizione switch
. Si noti che il tipo enum
viene utilizzato anche per definire valori costanti per casi diversi.
#include <stdio.h>
#include <stdlib.h>
enum TYPE { INTEGER, DOUBLE, INVALID };
#define typename(x) \
_Generic((x), int: INTEGER, double: DOUBLE, default: INVALID)
typedef void (*FuncPtr)();
void printInt(int x) { printf("printed from printInt: %d\n", x); }
void printDouble(double x) { printf("printed from printDouble: %f\n", x); }
int main() {
int input1 = 10233;
double input2 = 11.234;
FuncPtr func_ptrs[] = {printInt, printDouble};
switch (typename(input1)) {
case INTEGER:
func_ptrs[INTEGER](input1);
break;
case DOUBLE:
func_ptrs[DOUBLE](input1);
break;
case INVALID:
printf("No corresponding type found!\n");
default:
break;
}
switch (typename(input2)) {
case INTEGER:
func_ptrs[INTEGER](input2);
break;
case DOUBLE:
func_ptrs[DOUBLE](input2);
break;
case INVALID:
printf("No corresponding type found!\n");
default:
break;
}
exit(EXIT_SUCCESS);
}
Produzione:
printed from printInt: 10233
printed from printDouble: 11.234000
Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.
LinkedIn Facebook