2015-06-01 2 views
7
void funcPtr(int a); 

int main(){ 
    int k=1; 
    void (*funcPtr2)(int); 

    funcPtr2 = (void*)(funcPtr); 
    // funcPtr2 = (void(*)(int))(funcPtr); 

    (*funcPtr2)(k); 
    return 0; 
} 

void funcPtr(int a){ 
    printf("%d", a); 
} 

Qual è la differenza tra (void*) e (void(*)(argument type) nella fusione del tipo di puntatore a funzione?Qual è la differenza tra (void *) e (void (*) (tipo di argomento)) cast?

Come risultato, non si verifica avviso.

È sbagliato? fusione

+0

'errore: la conversione non valida da 'void *' a 'void (*) (int)'' – user657267

+0

perché uno getto, in primo luogo. Il puntatore funzione e la funzione indirizzata * corrispondono *? E tu sei parzialmente corretto; non c'è avviso, [è un errore flat-out] (http://ideone.com/8BpCPx) – WhozCraig

+6

C o C++? Sceglierne uno_. –

risposta

7

Is this wrong? about (void*) type casting

Si circa (void*) tipo, lo è.

C standard non consente la conversione di un puntatore di funzione in un puntatore dell'oggetto o un'assegnazione tra di essi. Se il vostro livello di avviso del compilatore, è possibile ottenere avvisi/errori come compilazione con:

gcc -Wall -Wextra -pedantic-errors -std=c11 file.c 

io non sono sicuro perché hai pensato di lanciare un puntatore a funzione. A condizione che il tipo di puntatore a funzione corrisponde alla funzione, è sufficiente assegnare:

funcPtr2 = funcPtr; 

parte:

È possibile utilizzare il puntatore a funzione, proprio come una funzione:

funcPtr2(k); 

e utilizzare un prototipo standard per main come:

int main(void) 
+0

La restrizione per disabilitare la conversione del puntatore del codice <-> risale ai giorni del modello di memoria Intel (http://en.wikipedia.org)/wiki/Intel_Memory_Model) e probabilmente aggeggi simili su altre architetture. Per esempio. sotto il modello "medio", 'sizeof (void *) == 2', ma' sizeof (void (*) (void)) == 4', rendendo le conversioni da e verso le conversioni non sicure. Naturalmente, nessuna di queste piattaforme e modelli di memoria ha alcuna rilevanza per quanto riguarda POSIX. –

0
(void*) 

lancia un puntatore a un puntatore per annullare o un puntatore generico.

void(*)(int) 

è un puntatore a funzione di una funzione che accetta un argomento int e non restituisce nulla.

int fn(float f) { return f * 3.14; } 

void* ptr = fn; 

renderebbe ptr l'indirizzo della prima istruzione macchina di fn, ma non consentono di utilizzare esso.

int(*ptr)(float) = fn; 
// or 
typedef int(FnPtr)(float); 
FnPtr* ptr = fn; 

prende l'indirizzo in modo che il compilatore sa che tipo di chiamata di funzione viene puntato in modo che si può chiamare la funzione

int n = ptr(2.5); 

che può essere utile per fare qualcosa di simile

void get_data(int socket, int timeout, void(*callback)(char*, size_t)); 

Quale è una funzione a cui posso passare un'altra funzione.

void recv_data(char* data, size_t len) 
{ 
    ... 
} 

... 

get_data(socket, 60, recv_data); 
+1

In C, non è possibile eseguire il cast di un puntatore a "void *". –

+0

@undur_gongor Alcuni compilatori lo consentono a determinati livelli di avviso, e lo sto facendo al mio acceso, quindi ho scelto di non discutere tale caso. – kfsone

+0

(Ma è per questo che scelgo 'would') – kfsone

1

questo è un problema con dlsym, dichiarata void *dlsym(void *restrict handle, const char *restrict name). dlsym restituisce un puntatore a una funzione denominata name definita in e accessibile tramite handle.
Tuttavia, come afferma @BlueMoon, questo non è definito in ISO C e gcc si lamenta in effetti se reso pedante. POSIX ha cercato di risolverlo e ha richiesto un'implementazione conforme per rendere quel cast ben definito nella sua indefinitezza.

Da POSIX

Note that conversion from a void * pointer to a function pointer as in:

fptr = (int (*)(int))dlsym(handle, "my_function");

is not defined by the ISO C standard. This standard requires this conversion to work correctly on conforming implementations.

Un altro modo per realizzare questo conforme cast è prima convertire il puntatore alla funzione di void** e poi dereferenziarlo. Questo dovrebbe essere ben definito. Nel tuo caso,

void funcPtr(int a); /* symbol to extract */ 

int main(void) 
{ 
    void (*fn)(int); 
    *(void**)(&fn) = dlsym(your_handle, "funcPtr"); 


    fn(5); 
}