Rzutowanie
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:
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:
Rzutowaniem jest właśnie przypisanie danych w ten sposób: Byte(VarC). W takim przypadku rzutujemy typ Char na Byte, w wyniku czego zmienna VarB 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:
Najlepiej omówić to na przykładzie. Oto prosty kod źródłowy, który na pewno nie zostanie prawidłowo skompilowany:
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:
Rzutowaniem jest właśnie przypisanie danych w ten sposób: Byte(VarC). W takim przypadku rzutujemy typ Char na Byte, w wyniku czego zmienna VarB 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:



Mianowicie:
W rzutowaniu zawsze zachodzi odwołanie do adresu pamięci w której przechowywana jest zmienna.
1) 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).
2) 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 ".
{$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!
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.
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ę:
{$APPTYPE CONSOLE}
uses
SysUtils;
var
a: string;
s: integer = 111;
begin
a:=string(s);
writeln(a);
readln;
end.
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ę
{$APPTYPE CONSOLE}
uses
SysUtils;
var
a: string = '111';
s: integer;
begin
s:=integer(a);
writeln(IntToStr(s));
readln;
end.
to zamiast 111 wyświetla 4227420
o co chodzi???