#programowanie #cplusplus #programista15k Zacząłem się interesować słynnym problemem Fast Inverse Square Root z Quakea. I w sumie mógłby mi ktoś powiedzieć jaką wartość posiadam pod zmienną wynikTestu? Dlaczego rzutowanie na inta daje dziwną wartość, a na floata normalną?
int main() { float test = 69.420; int wynikTestu = *(int*)&test cout<<wynikTestu<<endl; }
@jaksa0: Binarnie. Tak samo masz pojedynczą i podwójną precyzję w liczbach zmiennoprzecinkowych. Wiadomo że nie da się dokładnie zapisać liczby zmiennoprzecinkowej. Masz mantysę gdzie się przechowuje liczbę po przecinku i cechę czyli wykładnik. Więc mam test zapisany we floacie a w wynik wpisuję zdereferowany adres pamięci czyli to co się pod nim znajduje. Mnie zastanawia dlaczego konwersja na (int*) czyli wskaźnik na inta daje taką dziwną wartość skoro wynikTestu jest
@jaksa0: Chodzi o to że jak rzutuję wskaźnik na wskaźnik na inta to wtedy to co jest pod adresem czyli liczba float jest niezmienione (więc bity zostają łącznie ze znakiem) i otwieram to po prostu jako inta?
@przemyslaw-maczka: tak, rzutowanie wskaźników nie zmienia tego, co pod tym adresem się znajduje. Zmienia się jedynie sposób w jaki adresy są inkrementowane oraz to jak wyłuskuje dane spod tego adresu (w tym przypadku odczytuje je tak jakby tam był int)
@przemyslaw-maczka: no tak, czemu miały by się zmieniać bity? 4 bajty to 4 bajty. Ty tylko mówisz teraz traktuj te 4 bajty pamięci jak by to był int nie float.
@przemyslaw-maczka: Tutaj masz jak to binarnie wygląda. W gruncie rzeczy pod spodem jest taka sama wartość tylko inaczej interpretowana. (W xmm0 jest przechowywana wartość wynikTestu. Interesuje cię w tym momencie ta 1 wartość z v4_float)
@Dalegor_: Znaczy ja mniej więcej wiedziałem jak (T*)działa, tylko jakoś nigdy w mojej historii programowania nie miałem okazji konwertować tak z float& do int* i chyba mnie to zaskoczyło aż za bardzo. Poniekąd żałuję że tutaj napisałem bo zamiast wyjaśnić sprawę to dostałem odpowiedź żebym się o kodzie binarnym uczył :D Mimo wszystko dzięki za poświęcony trud.
Edit: może jednak nie wiedziałem skoro zaskoczeniem także było int wynikTestu =
Edit: może jednak nie wiedziałem skoro zaskoczeniem także było int wynikTestu = *(float*)&test że działa poprawnie :D
@przemyslaw-maczka: Tutaj już zasługa kompilatora za implicit conversion. W tym przypadku kompilator stara się przekonwertować floata na inta w miarę bezstratnie i o dziwo bezpośrednio za pomocą instrukcji procesora (w moim przypadku CVTTSS2SI, sam sposób konwersji może się różnić). Masz tutaj picrel jak to działa w kodzie assembly.
@przemyslaw-maczka: i dobrze, że nie miałeś okazji. Fajnie jest raz czy dwa to zobaczyć i przekonać się jak są przechowywane dane w komputerze, ale w kodzie produkcyjnym rzutowanie wskaźników to źródło potencjalnych trudnych do znalezienia błędów. Szczególnie w c++, gdzie w ogóle powinno się w miarę możliwości unikać gołych wskaźników.
Zacząłem się interesować słynnym problemem Fast Inverse Square Root z Quakea. I w sumie mógłby mi ktoś powiedzieć jaką wartość posiadam pod zmienną wynikTestu? Dlaczego rzutowanie na inta daje dziwną wartość, a na floata normalną?
int main()
{
float test = 69.420;
int wynikTestu = *(int*)&test
cout<<wynikTestu<<endl;
}
@Arkadio88: Wyłożyłem się na tak prostej sprawie :D
(T*)
działa, tylko jakoś nigdy w mojej historii programowania nie miałem okazji konwertować tak z float& do int* i chyba mnie to zaskoczyło aż za bardzo. Poniekąd żałuję że tutaj napisałem bo zamiast wyjaśnić sprawę to dostałem odpowiedź żebym się o kodzie binarnym uczył :D Mimo wszystko dzięki za poświęcony trud.Edit: może jednak nie wiedziałem skoro zaskoczeniem także było
int wynikTestu =
@przemyslaw-maczka: Tutaj już zasługa kompilatora za implicit conversion. W tym przypadku kompilator stara się przekonwertować floata na inta w miarę bezstratnie i o dziwo bezpośrednio za pomocą instrukcji procesora (w moim przypadku CVTTSS2SI, sam sposób konwersji może się różnić). Masz tutaj picrel jak to działa w kodzie assembly.