2013-03-09 29 views
6

Używam tej biblioteki C w mojej aplikacji C++, a jedna z funkcji zwraca void *. Teraz nie jestem najostrzejszy z czystym C, ale słyszałem, że pustka * może być rzucana do prawie każdego innego typu *. Wiem też, że oczekuję float na końcu gdzieś z tej funkcji.void * to literówka, jak rzutować?

Więc wyrzuciłem pustkę * do pływaka * i wyłączyłem pływak *, zderzenie. cerować!. I debugowania kodu i gdb niech to ocenić (float)voidPtr i niski i oto wartość jest tym, czego oczekuję i potrzebuję!

Ale czekaj, nie da się tego samego podczas kompilacji. Jeśli piszę float number = (float)voidPtr;, to nie kompiluje się, co jest zrozumiałe.

A teraz pytanie: jak mogę uwolnić się od tej szalejącej pustki *?

EDYCJA: Dzięki H2CO3 został rozwiązany, ale widzę wiele odpowiedzi i komentarzy pojawiających się i znikających nie wierząc, że mógłbym zrobić (float) voidPtr w gdb. oto zrzut ekranu.

enter image description here

+2

Oczywiście, lepsze rozwiązanie nie kończy się na takiej sytuacji. – delnan

+3

@delnan, więc OP powinien zrezygnować z całej biblioteki, ponieważ używa wskaźników void? –

+1

@CoreyOgburn Nie, mówię o nieinterpektywie interpretowanej jako wskaźnik pustej przestrzeni. 'void *' w niektórych przypadkach jest w porządku, ale w przypadku OP, ktoś gdzieś spieprzył. Być może OP źle używa biblioteki. – delnan

Odpowiedz

12

Spróbuj użyć wskazówek:

void *theValueAsVoidPtr = // whatever 

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

Należy zauważyć, że zakłada to, że 'sizeof (float) == sizeof (void *)', które może nie być prawdziwe, iw takim przypadku wywołuje niezdefiniowane zachowanie. –

+1

To działa, brakowało mi dodatkowego &. Nie wiem, co i dlaczego to się teraz dzieje, ale działa. dzięki. – xNidhogg

+1

@ xNidhogg Objaśnienie: bezpieczeństwo wskaźników wskaźników jest słabsze niż wskaźników bez wskaźników. Nie możesz rzucić 'void *' na 'float', ale możesz rzucić' void ** 'na' float * '. Teraz, gdy to zrobisz i usuniesz adres zmiennej 'theValueAsVoidPtr', otrzymasz * zawartość * tej zmiennej, tylko w innym typie - to się nazywa typem punning. Zobacz [wiersz oznaczony "zła zmiennoprzecinkowa wersja bitowa"] (http://en.wikipedia.org/wiki/Fast_inverse_square_root#Overview_of_the_code). –

8

Jeśli dobrze rozumiem, biblioteka zwraca wartość pływak w zmiennej, której zadeklarowanym typem jest void *. Najbezpieczniejszym sposobem, aby dostać go z powrotem znowu jest z 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; 
} 

przeciwieństwie do podejścia przyjętego odpowiedź, to nie powoduje zachowanie niezdefiniowany.