2012-06-04 20 views
6

Ciao amici,
How can I use an array of function pointers?
Se vedremo il collegamento sopra, ci dice come funziona il puntatore di funzione.
Ora la domanda è: perché dovrei scegliere il puntatore funzione?
Perché non posso utilizzare direttamente la chiamata di funzione?
Quali sono i vantaggi che otterrò con il puntatore di funzione?
esempioQual è la differenza tra Function Pointer vs Function Call?

enum{a, b, c}; 
void A(); 
void B(); 
void C(); 
void (*fun[3])() = {A, B, C}; 

Now when I need to call a function I am doing like, 
fun[a](); // This calls function A 
// And so on... 

stesso può essere fatto in funzione di chiamate anche

come quando ho bisogno di chiamare la funzione A, B o C. direttamente posso destra come

A(); 
B(); 
or 
C(); 

Allora perché function pointer?

+2

Non so perché ci sono due voti negativi alla mia domanda. Ma una cosa che so, non significa che se sai qualcosa che tutti dovrebbero conoscere. Comunque voti + ve o -ve non importa finché i miei dubbi vengono chiariti. –

risposta

5

Ora la domanda è: perché dovrei scegliere il puntatore di funzione?
Quali sono i vantaggi che otterrò con il puntatore di funzione?

È possibile utilizzare i puntatori di funzione quando è necessario implementare un meccanismo asincrono.
È necessario chiamare una funzione in modo asincrono quando si verifica qualcosa.
Come saprai quale funzione chiamare?
L'indirizzo di ogni funzione è univoco, quindi è necessario utilizzare e memorizzare l'indirizzo della funzione.
Dove memorizzi questo indirizzo di funzione?
Una funzione puntatore

2

Function I puntatori sono puntatori (come puntatori variabili) che puntano all'indirizzo di una funzione. In realtà chiamano la funzione sottostante quando li si denomina come fa una chiamata di funzione.

Il vantaggio principale di un puntatore a funzione è che si può passare ad un'altra funzione come parametro per esempio ...

3

Nella mia esperienza, i puntatori a funzione sono utilizzati principalmente per passare una funzione come parametro ad un'altra funzione.

Guardando il tuo codice, potrebbero anche essere usati come con gli array, quindi puoi semplicemente scorrere l'intero array (che potrebbe consistere di centinaia di puntatori di funzione) e li eseguirà tutti.

11

Ci sono molte ragioni per usare un puntatore a funzione, in particolare per fare le cose genericamente in C.

Il luogo principale vedrete che siano usate sono come argomento di una funzione.Ad esempio con la funzione bsearch, si utilizza una funzione di confronto, passata come un puntatore alla funzione, per confrontare gli oggetti e ordinare i dati:

void *bsearch(const void *key, const void *base, 
        size_t nmemb, size_t size, 
        int (*compar)(const void *, const void *)); 

Ciò permette bsearch di essere generico e ordinare qualsiasi tipo di dati, poiché solo che la funzione di confronto deve conoscere il tipo di dati.


Un altro ha a che fare con l'evitamento di controlli multipli. vale a dire.

void makePizza(void) { } 

void bakeCake(void) { } 

iWantPizza = 1; 
... 
if (iWantPizza) 
    makePizza(); 
else 
    bakeCake(); 
/* want to call the same function again... */ 
if (iWantPizza) 
    makePizza(); 
else 
    bakeCake(); 

.. 

/* alternative */ 
void (*makeFood)(void) = iWantPizza ? makePizza : bakeCake; 

makeFood(); 
/* want to call the same function again... */ 
makeFood(); 
6

Per l'esempio che hai mostrato, si può fare ancora una cosa.

Diciamo che ci sono molte funzioni che devono essere eseguite per alcune operazioni del dispositivo. In modo semplice, è possibile scrivere tutte le chiamate di funzione in un'altra funzione master e chiamare la funzione master .

Un altro modo per farlo è scrivere tutti i nomi di funzione in una parentesi graffa e chiamarli utilizzando un puntatore di funzione e un ciclo. Sembra intelligente. Non sono sicuro di come questo ti aiuti in modo migliore, ma l'ho visto nel codice del kernel di Linux.


Sono d'accordo a tutte le risposte qui. Oltre a questo ho alcuni dei miei giudizi per usare il puntatore di funzione.

Prendiamo un esempio di alcuni calcoli matematici complessi (come la stampa di Fibonacci, l'integrazione, Fourier Xform, ecc ...).

Hai una funzione FX (che fa complicato calcolo matematico o qualsiasi altra cosa) che usi molte volte nel tuo programma. Questa funzione è utilizzata in molti lavori diversi.

Dopo aver utilizzato il programma per alcuni mesi, si scopre che, per alcuni lavori, è possibile migliorare la funzione e per alcuni, quella corrente è la migliore. Cosa farai? Scrivi una nuova funzione, vai e cambia il nome della funzione in tutti i posti.

Ogni volta che trovi qualcosa di meglio, lo farai.

Invece, utilizzare un puntatore a funzione diversa per lavori diversi. Nella fase iniziale, tutti i puntatori possono puntare a una funzione. Quando si scopre una funzione migliore per un lavoro, basta deviare il puntatore e il gioco è fatto.


Prendere un altro scenario. Qui, hai un vero grande codice come il sistema operativo del telefono cellulare. (non completamente aperto ma mezzo compilato). È necessario aggiungere un driver Bluetooth ad esso per un particolare hardware.

Ora, è possibile aggiungere o è possibile lasciare è l'opzione disponibile nel sistema operativo.

Potrebbe essere necessario attivare/disattivare il Bluetooth da più posizioni.

Quindi il sistema operativo è un puntatore a funzione che attiva il bluetooth e lo utilizza ovunque sia necessario. Questo codice è già compilato, quindi non puoi aggiungere il tuo codice. Ma ciò che può essere fatto è che puoi scrivere la funzione e fare in modo che quel puntatore punti alla tua funzione.

Questo è ciò che ho già visto su sistema operativo Android.(non esattamente ma più vicino)

+1

Mi piace molto l'esempio con il calcolo matematico complesso. – johnny

3

Qual è la differenza tra Puntatore funzione e Chiamata funzione?

E 'come la differenza tra chiedere al compilatore di "dimmi l'indirizzo della National Gallery (I potrebbe desiderare di andare lì più tardi e voglio essere pronto a farlo)", piuttosto che "portami la National Gallery adesso (ma non presterò attenzione a come mi porti lì quindi non aspettarti che lo sappia più avanti) ". Fondamentalmente, se chiedi l'indirizzo/puntatore, puoi scriverlo in un posto come "il grande viaggio della prossima domenica pomeriggio" ... non devi neppure ricordarti che è la National Gallery a cui andrai - può essere una piacevole sorpresa quando arrivi lì, ma sai immediatamente che l'intrattenimento della domenica è tutto organizzato.

Quali vantaggi otterrò con il puntatore funzione?

Beh, come sopra, al momento di impostare il puntatore a funzione è necessario prendere una decisione su dove si chiami più tardi, ma poi si può dimenticare tutte le ragioni per fare tale decisione e sufficiente sapere che la destinazione successiva è pronta per l'uso. Nel momento in cui in realtà stai facendo cose ... "la mia routine domenicale: dormi fino a 10, fai una grande colazione, torni a letto, fai una doccia, se ho un sacco di soldi allora vai la domenica Grande viaggio pomeridiano, incontro con gli amici per cena "... la precedente decisione prende a calci per portarti alla galleria. In modo cruciale, puoi continuare a usare il tuo programma domenicale e iniziare a "puntare" l'indirizzo/puntatore del "prossimo viaggio pomeridiano del pomeriggio" in nuovi posti mentre attirano la tua attenzione, anche se non esistevano quando si è formato il tuo programma generale.

Si vede questa flessibilità post-facto per cambiare la destinazione inviata a un passo in una vecchia routine illustrata bene dalla menzione di AusCBloke su bsearch. qsort è un altro esempio classico: conosce la grande logica dell'immagine per l'ordinamento efficiente di array di cose arbitrarie, ma deve essere detto dove andare per confrontare due delle cose per le quali lo stai effettivamente usando.

1

Questi sono buoni esempi, in particolare il primo in Urvish sopra. Mi sono chiesto la stessa cosa, e penso che la risposta sia puramente di design. Nella mia mente, sono lo stesso risultato, in quanto puoi puntare a una funzione e ottenere un + b oppure puoi semplicemente chiamare una funzione regolarmente e ottenere un + b, e con gli esempi su SO, sono di solito piccoli e banali per illustrazione. Ma, se uno avesse un programma C in 10k linea, e dovessi cambiare qualcosa cinquanta volte perché hai apportato una modifica, probabilmente avresti capito molto rapidamente perché volevi usare i puntatori di funzione.

Ti fa apprezzare anche il design dei linguaggi OOP e la filosofia dietro OOD.

Problemi correlati