2016-06-04 40 views
5

Supponendo che tutte le funzioni condividano lo stesso tipo di ritorno, è valido chiamarle ognuna con un puntatore di funzione "generico", che viene dichiarato con parentesi vuote (quindi non specifica gli argomenti)?È consentito chiamare funzioni con prototipi diversi da un puntatore a funzione pseudo-generica?

Ecco un esempio di codice, che lo illustra:

#include <stdio.h> 

void fun1(void) 
{ 
    printf("fun1\n"); 
} 

void fun2(int a) 
{ 
    printf("fun2: %d\n", a); 
} 

void fun3(int a, int b) 
{ 
    printf("fun3: %d %d\n", a, b); 
} 

int main(void) 
{ 
    void (*pf)(); // pseudo-generic function pointer 

    pf = fun1; 
    pf(); 

    pf = fun2; 
    pf(0); 

    pf = fun3; 
    pf(1, 2); 

    return 0; 
} 
+1

Possibile duplicato di [Puntatore funzione senza tipi di argomenti?] (Http://stackoverflow.com/questions/20835534/function-pointer-without-arguments-types) –

+0

Interessante domanda. Valido come in "compilazione ed esecuzione come previsto?" si, dice "compilare con il lavoro di' -Wall' senza avvertimenti? " sui miei compilatori sì :-) – Dilettant

+0

Sì, nessun avvertimento nemmeno in modalità paranoico '-Wall -Wextra -pedantic -Wconversion' di GCC 4.9 ... @Dilettante – alk

risposta

6

Si può fare cose simili, ma non esattamente in quel modo. Quando chiamate una funzione attraverso un puntatore a funzione, dovete essere sicuri che il prototipo sul lato chiamante sia esattamente come la funzione è stata definita.

Ora una dichiarazione di funzione con parentesi vuota non è nemmeno un prototipo, quindi questo non è il modo giusto per chiamarlo. Il motivo principale è che la convenzione di chiamata potrebbe essere leggermente diversa da quella che ci si aspetterebbe. Per le funzioni () si applicano regole speciali, vale a dire i tipi stretti vengono convertiti in int, unsigned o double.

Ora quello che si può fare è negozio un puntatore a funzione in pf come si fa, ma poi si era sempre necessario riconvertirlo al puntatore corretto funzionamento prima della chiamata, come ad esempio

((void (*)(int, int))pf)(a, b); 

Questo è appena leggibile e molto errorprone. Dovresti evitare questa ginnastica il più possibile.