Avvertimento quando il tipo di fusione tra puntatore e puntatore a funzione
Domanda
sto porting del codice C per un ambiente di chip di TI DSP. Sono alle prese con il compilatore C.
Ho una struttura di dati che include un puntatore a una funzione. Ho una funzione che inizializza la struttura dei dati. Qualcosa di simile a questo:
typedef void (*PFN_FOO)(int x, int y);
struct my_struct
{
PFN_FOO pfn;
};
init_struct(struct my_struct *p, void *pfn)
{
p->pfn = (PFN_FOO)pfn;
}
In Visual Studio e GCC questo tipo di codice venga compilato senza lamentarsi. In realtà, perché l'argomento è di tipo pfn
void *
non ho davvero bisogno di mettere anche un cast lì; sarebbe solo implicitamente espressi, senza denuncia.
In Code Composer Studio per i chip DSP TI, ottengo "warning: conversione del tipo non valido"
La mia politica è quella di rendere il mio codice compilato senza avvisi, quindi voglio risolvere questo problema. Ho provato tutti i tipi di casting. Ho scoperto che il compilatore è perfettamente felice se io scaccio il puntatore void *
a int
prima, e poi il cast al tipo corretto. Ew, che schifo!
Come posso fare questo cast senza il compilatore lamentarsi? Devo davvero a gettare a int
di chiudere il compilatore?
Nota: Sono specificamente non alla ricerca di una soluzione per l'effetto di "cambiamento init_struct()
ad accettare un PFN_FOO
invece di un void *
". Che avrebbe funzionato per questo frammento di codice semplificato, ma non avrebbe funzionato per il codice vero e proprio, che crea un elenco di cose possibilmente eterogenee.
Soluzione
standard C specificamente non supporta le conversioni tra puntatori a oggetti di dati e puntatori a funzioni. GCC e Visual Studio supportano questa come estensione.
Se si desidera rendere il vostro funzione standard conforme (ma ancora utilizzare il parametro void *
), si potrebbe passare un puntatore a un puntatore a funzione, invece. Questo funziona perché la funzione puntatori stessi sono oggetti comuni, in modo da un puntatore a un puntatore a funzione può essere convertita da e per void *
bene:
init_struct(struct my_struct *p, void *pfn)
{
PFN_FOO *foo = pfn;
p->pfn = *foo;
}
Il chiamante deve quindi creare un oggetto PFN_FOO
temporaneo per passare un puntatore a quando si effettua la chiamata:
PFN_FOO fp = &somefunc;
/* ... */
init_struct(p, &fp);
Altri suggerimenti