2015-07-24 9 views
5

Possiamo inserire un indirizzo di funzione di una particolare firma in un puntatore di funzione che è definito per avere qualche altra firma e usarlo senza problemi?Può essere compatibile una coppia di puntatori a funzioni diverse che accettano diversi tipi di parametri?

Ad esempio, il seguente codice di

#include <stdio.h> 

void print_n(int *pn) { 
    printf("%d\n", *pn); 
} 

void print_n_wrapper(void *p) { 
    print_n(p); 
} 

int main(void) { 
    int n = 123; 
    void (*f)(void *) = print_n_wrapper; 
    f(&n); 
    f = print_n; 
    f(&n); 
    return 0; 
} 

viene compilato e funziona bene nella mia macchina. Sto invocando in qualche modo un comportamento indefinito?

+0

Sì, si sta invocando UB. Quei tipi di puntatore non sono compatibili. –

+0

Trova lavoro, ma il compilatore ti dice 'warning: assegnazione da tipo di puntatore incompatibile' – LPs

risposta

8

Sì, è undefined behaviour.

Citando C11, capitolo §6.3.2.3, puntatori, (sottolineatura mia)

Un puntatore a una funzione di un tipo può essere convertito in un puntatore a una funzione di altro tipo e di nuovo indietro; il risultato deve essere uguale al puntatore originale. Se un puntatore convertito viene utilizzato per chiamare una funzione il cui tipo non è compatibile con il tipo di riferimento, il comportamento non è definito.

e relativo "funzione il cui tipo non è compatibile" parte, la definizione della compatibilità va come

Per due tipi di funzioni siano compatibili, sia particolare indica tipi restituiti compatibili. (146) Inoltre, gli elenchi dei tipi di parametri, se entrambi sono presenti, devono concordare nel numero dei parametri e nell'utilizzo del terminatore ellittico; i parametri corrispondenti devono avere i tipi compatibili .

Ciò significa, void * e int *avrebbe dovuto essere gli stessi tipi, ma essi non sono . Quindi, anche le funzioni non sono di tipo compatibile.

+0

OP chiede se i suoi due tipi di funzione sono * compatibili *, quindi la tua risposta dovrebbe andare in quello che significa che i tipi di funzione sono compatibili –

5

La chiamata a print_n(p) in print_n_wrapperè definito poiché tutto quello che stai facendo è la conversione di un void* che originariamente era una int* a un int*

L'assegnazione f = print_n; vi darà problemi. Sebbene l'assegnazione sia definita, il comportamento alla chiamata successiva f(&n)è un valore non definito.

Problemi correlati