Rzutowanie
Adam Boduch
Rzutowanie to sposób na ?oszukanie? kompilatora. Jeżeli nie jesteśmy pewni, co robimy, możemy w konsekwencji doprowadzić do wystąpienia poważnych błędów podczas działania programu.
Najlepiej omówić to na przykładzie. Oto prosty kod źródłowy, który na pewno nie zostanie prawidłowo skompilowany:
var C: Char;
B: Byte;
begin
C := 'A';
B := C;
end.
Dane w postaci Char (pojedynczy znak) próbujemy tu przypisać do zmiennej VarB, która jest zmienną typu Byte. Oczywiście kompilator wskaże błąd: [Error] typcast.dpr(12): Incompatible types: 'Byte' and 'Char'. Po drobnej modyfikacji cały program zostanie skompilowany prawidłowo i zadziała bez problemu:
var C: Char;
B: Byte;
begin
C := 'A';
B := Byte(C); // rzutowanie
end.
Rzutowaniem jest właśnie przypisanie danych w ten sposób: Byte(C)
. W takim przypadku rzutujemy typ Char na Byte, w wyniku czego zmienna B będzie posiadać wartość 65
(kod ASCII litery A).
Funkcja Messagebox wymaga typu PChar (który również jest typem znakowym), zatem należy zastosować następujące rzutowanie:
MessageBox(0, PChar(IntToStr(Zmienna_Integer)), 'Tytuł programu', MB_ICONINFORMATION);
- Zobacz też: **
- Konwersja typów
- Typy danych
Jestem nowy (user) ale raczej kumam o co chodzi.
Mianowicie:
W rzutowaniu zawsze zachodzi odwołanie do adresu pamięci w której przechowywana jest zmienna.
w pierwszym rzutowaniu następuje odwołanie do adresu zmiennej typu integer (integer to 32 bity = 4 bajty). Na jej danych chcemy utworzyć zmienną typu string. Problem jest jeden ... string to ciąg znaków (może być pusty) zawsze zakończony dwoma bajtami o wartości zero. Tak więc rzutowanie (i tym samym wymuszanie) aby z wartości nie zakończonej zerem zrobił się string nie ma zbyt dużych szans. Problemem staje się to, że programy mogą odwoływać się tylko do przedziału pamięci zadeklarowanej w programie - jakiekolwiek odwołanie się poza ten przedział zawsze wywoła naruszenie bezbieczeństwa systemu (lub czegoś w tym stylu).
w drugim rzutowowaniu znowu następuje odczyt danych spod adresu zmiennej - tej z której rzutujemy. W tym przypadku następuje przekształcenie z pamięci XX XX XX 00 00 (czyli: znak, znak, znak, 00, 00 - string '111' zajmuje 5 bajtów). Ciąg '111' powinien dokładnie wyglądać (szesnastkowo) tak: 31 31 31 00 00. Zmienna typu string (tak jak i każda inna zmienna) to wskaźnik do adresu pamięci - string wskazuje na pierwszy bajt pamięci (pierwszy znak ciągu). Zmienna typu integer jak już mówiłem to 4 bajty a więc odczytuje ona tylko pierwsze cztery (z pięciu) ze zmiennej string. Jednym słowem w tym przypadku konwersja (rzutowanie) to pikuś - Pan Pikuś.
Przy rzutowaniu trzeba znać się na typach pamięci - wszystko jest w helpie ... jeżeli chodzi o typy zmiennych. Trzeba zapamiętać jedno - nie wszystko da się zrzutować!
PS. W opisie odwołuję się do "FALCO dnia 19-04-2006 19:01 ".
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
a: ShortString = 'A';
s: integer;
begin
//: Zmienna a w pamięci w zapisie HEX wygląda tak:
//: 41000000000000....00
//: Jest to 41 i 254x00
//: I teraz rzutujesz to, a że Integer to 4bajty to zrzutuje tylko
//: 41000000
//: I otrzymasz liczbę która w zapisie Hex to 41000000 czyli w Dec 65
s:=integer(a);
writeln(IntToStr(s));
readln;
end.
Przynajmniej tak zrozumialem. To tylko moja teoria. Możesz włączyć debugera zmienną dodać do Watch i ustawić typ jako 'Memory Dump'.
Powodzenia!
mo wiem że można IntToStr(liczbaktóramabyćłańcuchem) ale chciałem sobie przetestować to rzutowanie więc biorę dwa najczęściej konwertowane typy a tu błąd i chciałbym wiedzieć czemu i jakie typy można a jakich nie można rzutować... jest może gdzieś spis typów które mogę rzutować?
W takim wypadku stosuj konwersje (poszukaj artykulu na ten temat).
Rzutowanie to jest sposob na oszukanie kompilatora, ale trzeba wiedziec co sie robi, w Twoim przypadku program nie dziala zgodnie z oczekiwaniami, nie mozna w ten sposob zmienic typu akurat tych zmiennych.
albo jestem głupi albo nie rozumiem...
z tekstu zrozumiałem że:
mam zmienną jakiegoś typu, mam inną zmenną innego typu
funkcja -> jakaś_zmienna := jakiś_typ(zmienna_innego_typu);
zamieni mi zmienną innego typu na zmienną jakiegoś typu
CZYLI...
próbuję:
niby powinno wyświetlić 111 ale wyskakuje wyjątek
czyli coś nie rozumiem ale przysięgam że przeczytałem ten tekst wiele razy i tyle samo (no może mniej) próbowałem to co powyżej przedstawiłem
a jak z kolei próbuję
to zamiast 111 wyświetla 4227420 :/
o co chodzi???