ProgrammazioneProgrammatore di sistema

Spiega le caratteristiche della dichiarazione e dell'uso di puntatori a funzioni in C. Come si può memorizzare correttamente un array di puntatori a diverse funzioni e richiamarle dinamicamente?

Supera i colloqui con l'assistente IA Hintsage

Risposta

Un puntatore a funzione in C è una variabile che memorizza l'indirizzo di una funzione, consentendo di scegliere dinamicamente quale funzione chiamare. La dichiarazione di un puntatore a funzione normale è:

// Puntatore a funzione che prende un int e restituisce un int int (*f_ptr)(int);

Per un array di puntatori:

int func1(int x) { return x + 1; } int func2(int x) { return x * 2; } int (*f_arr[2])(int) = { func1, func2 }; int result = f_arr[1](10); // restituirà 20
  • Questo approccio consente di creare tabelle di comandi, gestori o di collegare automaticamente azioni con il numero dell'operazione.
  • Tutte le funzioni devono avere la stessa firma.
  • Quando si lavora con puntatori a funzioni, i tipi devono corrispondere esattamente.

Domanda ingannevole

Si può chiamare una funzione con un'altra firma utilizzando un puntatore a funzione?

Risposta errata comune: "Sì, se si utilizza il casting del tipo".

Risposta corretta: Tecnologicamente è possibile a causa della natura dinamica dei puntatori, ma tale azione porta a bug a runtime e comportamenti imprevedibili, poiché vengono chiamate funzioni con differenti convenzioni di chiamata e composizione degli argomenti.

Esempio:

void funcA(int x) { printf("A: %d\n", x); } void funcB(float y) { printf("B: %f\n", y); } void (*fptr)(int) = (void (*)(int)) funcB; fptr(5); // ERRORE: verranno passati dati errati

Esempi di errori reali dovuti alla mancata comprensione delle sottigliezze dell'argomento


Storia

In un progetto di sistema di plugin sono state inserite nella tabella dei puntatori funzioni con firme diverse (una restituiva int, l'altra void). Lorsono state eseguite alcune architetture, causando danni allo stack.

Storia

In un vecchio sistema di gestione dei comandi si utilizzava un array di puntatori a funzioni. Un neofita ha aggiunto una funzione con parametri aggiuntivi, il che ha causato un'esecuzione imprevedibile dopo il passaggio al nuovo elemento dell'array.

Storia

Nel firmware non è stato controllato il risultato della modifica dei puntatori a funzioni. Un'inizializzazione insufficiente dell'array di gestori ha portato alla chiamata di un puntatore nullo (NULL), dopo di che il dispositivo si bloccava senza notificare l'utente.