XII.  

PŘETYPOVÁNÍ


Data jsou uchovávána v operační paměti ve své vnitřní binární reprezentaci. Typem proměnné, která je na uvažovaném úseku oprační paměti alokována, je určena jednak velikost a struktura úseku (členění na dílčí komponenty), jednak množina jazykem definovaných operací, které lze pro zpracování hodnoty úseku použít. Při překladu zdrojového textu programu je v tomto směru prováděna přísná typová kontrola, kterou zmírňují pouze pravidla kompatibility typů. V určitých případech však typ proměnné není znám (například při referenci univerzálním ukazatelem) nebo je výhodné jej dočasně nahradit typem požadovaným. Změnu deklarovaného typu proměnné nebo implicitního typu hodnoty výrazu lze vynutit požadavkem na jeho přetypování (typecasting).

XII.1. 

Přetypování proměnné

V zápisu operace přetypování proměnné je uveden identifikátor požadovaného typu (nebo string nebo file) a v závorkách proměnná, která má být přetypována.

Obrázek 67: Operace přetypování proměnné

Výsledkem operace je proměnná požadovaného typu, alokovaná na stejném úseku operační paměti jako proměnná původní. Původní typ proměnné nesmí být procedurální a musí mít stejnou velikost jako typ požadovaný, jinak mohou být oba typy libovolné.

type PtrRec = record
               Ofset, Segment: Word
              end;

var  P      : Pointer;
     Q      : ^Byte;
     S      : string;
...
with PtrRec(P) do                { vynucení typu PtrRec           }
 begin
  Ofset   := 1000;               { týž efekt jako přiřazovací     }
  Segment := 0                   { příkaz P := Ptr (0, 1000)      }
 end;
Byte(S) := ...                   { nedovolené přetypování - různé }
                                 { velikosti typů Byte a string   }
Požadavek stejné velikosti deklarovaného a požadovaného typu proměnné lze obejít použitím reference proměnné typovým nebo netypovým ukazatelem. Typ proměnné, která je výsledkem operace přístupu k referované proměnné, je totiž nezávislý na zdroji hodnoty ukazatele (v následujícím příkladu jím je proměnná S) — pro typové ukazatele je roven jejich bázovému typu a pro univerzální ukazatele není definován.
Q := @S;                         { Q ukazuje na S                 }
Q^ := ...;                       { Q^ je proměnná typu Byte,      }
                                 { alokovaná v prvním bytu S      }

P := @S;                         { P ukazuje na S                 }
P^ := P^;                        { chyba - typ P^ není definován, }
                                 { není tudíž slučitelný ani sám  }
                                 { se sebou                       }
Byte(P^) := ...;                 { Byte(P^) je proměnná typu Byte,}
                                 { alokovaná v prvním bytu S      }
string(P^) := ...;               { string(P^) je proměnná typu    }
                                 { string, totožná s proměnnou S  }
Univerzálním ukazatelem referovanou proměnnou lze tedy přetypovat libovolným typem, aniž by došlo ke kolizi velikosti původního (nedefinovaného) a požadovaného typu.

XII.2. 

Přetypování výrazu

Turbo Pascal implementuje řadu standardních konverzních funkcí (například Ord, Chr, Trunc, Round, ...), umožňujících převody hodnot mezi určitými typy. Pro konverzi hodnot mezi dalšími typy, pro něž konverzní funkce implementovány nejsou, lze použít operaci přetypování (hodnoty) výrazu.

Obrázek 68: Operace přetypování výrazu

Ze syntaktického hlediska se operace přetypování výrazu podobá operaci přetypování proměnné, argumentem závorky však nemusí být proměnná, nýbrž výraz, a výraz je i výsledkem operace. Požadovaný a původní typ výrazu nemusí mít stejné velikosti, každý z nich však musí být ordinálním nebo ukazatelovým typem. Při konverzi mezi celočíselnými typy zůstává znaménko původní hodnoty výrazu zachováno, pokud je požadovaný typ typem se znaménkem (ShortInt, Integer, LongInt nebo jejich interval).

type Barva = (Cervena, Zelena, Modra);
var  Byt   : Byte;
     Bol   : Boolean;
     Int   : Integer;
     Poi   : Pointer;
     Bar   : Barva;
     Lon   : LongInt;
...
Byt := Byte(256 * 2 + 1)                      { = 1               }
Bol := Boolean(3 * Byt mod 2);                { = True            }
Int := Integer(not Bol);                      { = 0               }
if not Boolean(Int) then                      { = not False       }
 Poi := Pointer(65536 * 10 + 7)               { = Ptr(10, 7)      }
else 
 Poi := Pointer(0);                           { = Ptr(0, 0) = nil }
Bar := Succ(Barva(Byt));                      { = Zelena          }
Int := 400;
Lon := Int * 300;                             { = -11072          }
Lon := Int * LongInt(300);                    { = 120000          }
...

XII.3. 

Netypové parametry podprogramů

Pokud ve specifikaci formálního parametru podprogramu není uveden jeho typ, jedná se o tzv. netypový parametr. Takový parametr musí být volán výlučně odkazem. Při volání je potom podprogramu předána (stejně jako u typových var-parametrů) přes zásobník adresa skutečného parametru, který je chápán jako proměnná nedefinovaného typu. Tato proměnná má stejné vlastnosti jako proměnná referovaná netypovým ukazatelem, takže jí lze pomocí operace přetypování proměnné přidělit libovolný typ.


PŘÍKLAD: Funkce Rovnost je univerzální funkcí, testující rovnost dvou proměnných libovolných typů (shodnost jednotlivých jejich bytů). Parametry PrvniDruhy jsou testované proměnné, Velikost je jejich velikost v bytech.

function Rovnost (var Prvni, Druhy; Velikost: Word): Boolean;
{-----------------------------------------------------------}

 type Maska = array [0 .. 65534] of Byte;
 var  N     : Word;

begin { Rovnost }
 N := 0;
 while (N < Velikost) and (Maska(Prvni)[N] = Maska(Druhy)[N]) do
  Inc(N);
 Rovnost := N = Velikost
end; { Rovnost }

Na proměnné PrvniDruhy je tedy využitím typecastingu pohlíženo jako na pole bytů. Test na rovnost pak probíhá mezi jednotlivými byty těchto polí. V každém průchodu tělem cyklu while je inkrementována hodnota indexu porovnávaných bytů, takže po skončení cyklu má výraz N = Velikost hodnotu True právě tehdy, když bylo uskutečněno Velikost průchodů jeho tělem — právě když se všechny porovnávané byty shodovaly.