2013-03-09 10 views
6

Quindi sto usando questa libreria C nella mia app C++, e una delle funzioni restituisce un void *. Ora non sono il più acuto con la pura C, ma ho sentito che un vuoto * può essere lanciato su praticamente qualsiasi altro tipo *. So anche che mi aspetto un float alla fine da qualche parte da questa funzione.void * è letteralmente fluttuante, come lanciare?

Così getto il void * a un float * e la dereferenziazione del float *, crash. maledettamente !. Eseguo il debug del codice e in gdb lascio valutare (float)voidPtr e basso ed ecco che il valore è quello che mi aspetto e di cui ho bisogno!

Ma aspetta, è impossibile lo stesso durante la compilazione. Se scrivo float number = (float)voidPtr; non viene compilato, il che è comprensibile.

Quindi ora la domanda, come faccio a liberarmi di questo vuoto *?

EDIT: Grazie a H2CO3 questo è stato risolto, ma vedo molte risposte e commenti che appaiono e scompaiono non credendo che potrei fare (float) voidPtr in gdb. ecco lo screenshot.

enter image description here

+2

Ovviamente, una soluzione migliore non finisce in una situazione come questa per cominciare. – delnan

+3

@delnan, quindi OP dovrebbe rinunciare a un'intera libreria perché utilizza i puntatori void? –

+1

@CoreyOgburn No, sto parlando di un non-pointer interpretato come un puntatore vuoto. 'void *' va perfettamente bene in alcuni casi, ma nel caso di OP, qualcuno da qualche parte ha sbagliato. Forse OP sta usando la libreria errata. – delnan

risposta

12

Prova usando puntatori:

void *theValueAsVoidPtr = // whatever 

float flt = *(float *)&theValueAsVoidPtr; 
+8

Si noti che questo assume che 'sizeof (float) == sizeof (void *)' che potrebbe non essere vero, e in questo caso invoca un comportamento non definito. –

+1

Funziona, mi mancava l'aggiunta di &. Non sono sicuro di cosa o perché esattamente ciò avvenga ora, ma funziona. Grazie. – xNidhogg

+1

@xNidhogg Spiegazione: il tipo di sicurezza dei puntatori è più debole dei non puntatori. Non puoi lanciare 'void *' in 'float', ma puoi lanciare' void ** 'in' float * '. Ora quando lo fai e dereferenzia l'indirizzo della variabile 'theValueAsVoidPtr', ottieni il * contenuto * di quella variabile, solo in un altro tipo - questo è chiamato punire tipo. Vedi la [linea contrassegnata con "hacking a livello di bit in virgola mobile malvagio"] (http://en.wikipedia.org/wiki/Fast_inverse_square_root#Overview_of_the_code). –

8

Se ho capito bene, la libreria restituisce un valore float in una variabile il cui tipo dichiarato è void *. Il modo più sicuro per farlo tornare di nuovo fuori è con un union:

#include <assert.h> 
static_assert(sizeof(float) == sizeof(void *)); 

union extract_float { 
    float vf; 
    void * vp; 
}; 

float foo(...) 
{ 
    union extract_float ef; 
    ef.vp = problematic_library_call(...); 
    return ef.vf; 
} 

differenza dell'approccio nella risposta accettata, questo non fa scattare un comportamento indefinito.