2010-07-05 9 views
6

In particolare, sarà il seguente mai non funziona come previsto:È sicuro chiamare i puntatori di funzione lanciati?

typedef void(*func_p)(void*); 

void foo(int* data) 
    { 
    printf("%i\n",*data); 
    } 

int main(int argc, char** argv) 
    { 
    func_p bar; 
    int x = 42; 

    bar = foo; 
    bar((void*)&x); 

    return 0; 
    } 

cioè, posso contare su puntatori dati (void*, int*, struct baz*, ma non neccesarily void(*)(void)) sempre essere passati compatably?

+0

c'è un modo per iscriversi a una domanda in modo da ricevere una notifica quando la sua risposta, senza lasciare questi stupidi commenti e rintracciarla attraverso di essa? –

+0

@Gollum: fai clic sulla stella vuota. Vedrai quindi eventuali modifiche nella scheda 'preferiti' della tua pagina delle modifiche recenti (facendo clic sulla busta in cima) – SLaks

+0

Grazie :) @SLaks, apprezzalo. –

risposta

7

Non è richiesto dallo Standard che funzioni. Lo standard richiede che char* e void* abbiano gli stessi requisiti di rappresentazione e allineamento, tutti i puntatori di struttura lo fanno e anche tutti i puntatori di unioni lo fanno. Sebbene sia un comportamento indefinito chiamare in ogni caso il puntatore della funzione casted (§6.5.2.2p9), gli stessi requisiti di rappresentazione e allineamento danno una garanzia pratica che la chiamata funzioni (§6.2.5p27).

Altri tipi di puntatore non devono comportarsi in questo modo, anche se non ho mai incontrato personalmente una macchina del genere. È teoricamente possibile che uno int* abbia un più piccolo di uno ad esempio (se lo standard ha uno standard di allineamento più severo rispetto a char, questa potrebbe essere una cosa ragionevole da fare). In base alla convenzione di chiamata corretta, su una macchina del genere sarebbe praticamente impossibile chiamare un puntatore a funzione casted.

+0

+1, anche se piuttosto deludente. –

+0

@David abbastanza francamente, se significa che avrei bisogno di creare dozzine di funzioni wrapper solo per poter passare la mia funzione come parametro a un tipo di questo tipo - avrei semplicemente lanciato :) –

+0

@litb, lo stavo facendo in quel modo per un mentre per esattamente questo motivo:] –

1

A meno che il tuo codice non sia mirato a vecchi e antichi mainframe, per tutti gli scopi pratici funzionerà correttamente. Nessuna macchina moderna usa rappresentazioni diverse per tipi di puntatore diversi, e non penso sia realistico che una macchina futura lo farà mai. È semplicemente illogico e arretrato, proprio come l'aritmetica del complemento a un altro.

Se sei ancora preoccupato o vuoi soddisfare i puristi della lingua, segui il suggerimento di caf.

+0

Ho avuto l'impressione che i puntatori-a-funzioni possano avere dimensioni diverse da puntatori a dati, oppure è una cosa C++? – kibibu

+0

È una cosa di Windows a 16 bit correlata all'idea di Microsoft di "modello di memoria" e puntatori vicini/lontani. Per chiarire: lo standard ** consente ** di essere diversi, ma non c'è motivo per cui dovrebbero mai essere diversi su un'architettura moderna. –

+0

@kibibu @R .. in realtà, avere puntatori di funzione più grandi dei puntatori di dati è abbastanza comune su microcontrollori e simili, poiché la memoria di programma può essere separata dalla memoria di dati e/o non scrivibile. –

Problemi correlati