Podczas kodowania w językach niskiego poziomu, takich jak CI, zauważ, że rzutowanie czasami oznacza „reinterpretuj te bajty, tak jakby zawsze był tego innego typu”, a innym razem jako „inteligentnie przekonwertuj tę wartość na ten inny typ”.
Jakie jest pierwotne znaczenie tego słowa i czy istnieje spójność, kiedy należy spodziewać się konwersji, a kiedy surowej interpretacji?
terminology
type-casting
Alexander Torstling
źródło
źródło
cast
w sensie komputerowym jest bardziej podobny do odlewania w sensie metalurgicznym, w którym kształt stopionego metalu ulega reformie po wlaniu do formy: britannica.com/EBchecked/topic/377665/metallurgy/81884/CastingOdpowiedzi:
Przesyłanie w C jest wyjątkowe, w przeciwieństwie do innych języków. Nigdy też nie jest inteligentny.
Rzutowanie w C konwertuje wartości z jednego typu na inny przy użyciu dokładnie zdefiniowanych reguł. Jeśli naprawdę potrzebujesz wiedzieć, przeczytaj standard. W przeciwnym razie główne punkty to:
Niektóre rzutowania są stosowane domyślnie, a w niektórych kompilator generuje ostrzeżenie. Najlepiej posłuchaj ostrzeżeń!
Słownikową definicję obsady najlepiej zignorować, ponieważ jest nieprzydatna. Wiele obsad jest lepiej opisanych terminami konwersja lub przymus, więc warto je też poznać.
C ++ jest DUŻO bardziej skomplikowany, ale o to nie pytałeś, prawda?
źródło
T*
navoid*
iz powrotem jest zawsze dobrze zdefiniowana.Ta część słownika Webster zawiera poprawną definicję:
Zatem przed rzutowaniem „obiekt” (nie dosłownie obiekt OOP) ma określony kształt (typ). Kiedy ponownie go rzucisz, czyli „wylejesz beton” wokół niego, aby nadać mu nowy kształt, to właśnie robisz z odlewem. Masz liczbę jako liczbę całkowitą w kształcie sześciokąta, a po rzuceniu otrzymasz ciąg w kształcie prostokąta.
źródło
Przydatne może być rozdzielenie rzutów C na dwie grupy:
Rzutowanie numeryczne - konwertuj liczbę między jedną reprezentacją na drugą, próbując zachować wartość. Na przykład -
(int)3.1
byłoby3
. Istnieją dokładne reguły określające, co dzieje się, gdy nie można zachować dokładnej wartości.Rzutowanie wskaźnika - Zachowaj adres pamięci, ale zmień sposób, w jaki jest wyrenderowany. Na przykład for
float x=3.5
,*(int *)&x
daje1080033280
- ta liczba całkowita jest reprezentowana przez ten sam wzór bitowy, który reprezentuje liczbę zmiennoprzecinkową3.5
.źródło
Keep the memory address, but change the way it's dereferenced.
Dereferencje wskaźnika pisanego czcionką nie są zdefiniowane. Standard gwarantuje tylko rzutowanie z miejscaA *
na miejsceB *
i z powrotem, co spowoduje, że będzie to samoA *
, co może nie być ważne dla dereferencji na pierwszym miejscu - lub, jeśliB *
jestchar *
, może być użyte do odczytania reprezentacji obiektu dowolnego typu. W przypadku wszystkich innych typówB *
wskaźnik dereferencji oznacza pisanie na klawiaturze, UB i narusza ścisłe aliasing. W każdym razie, nawet jeśli z tego powodu kompilator nie zniszczył powyższego przykładu 2, przyjmujesz nieportowalne założenia dotyczące wzorów bitowychW C ++ różne rodzaje rzutowań mogą być bardziej wyraźne,
reinterpret_cast
co oznacza „traktuj te bajty tak, jakby były już inną rzeczą”. W C można to absolutnie jednoznacznie określić za pomocą aunion
, rzutowanie z(type)
operatorem będzie próbowało zachować wynik liczbowo równoważny, aż do utraty precyzji.źródło
int*
, miał jedno słowo ichar*
dwa słowa [drugi bajt wybiera najwyższy lub najniższy bajt słowa]. Rzutowanie(int*)
na(char*)
wymagałoby dodania dodatkowego słowa, które powinno być dowolną wartością określającą pierwszy bajtint
.