XIII. |
TYPY PROCEDURA |
Turbo Pascal implementuje prostředky pro spouštění podprogramů, aktuálně volených až v průběhu výpočtu programu, a také pro předávání takto zvolených podprogramů procedurám a funkcím formou procedurálních parametrů.
Deklarace typu procedura Popis typu procedura odpovídá (až na chybějící identifikátor) hlavičce procedury nebo hlavičce funkce. Identifikátory formálních parametrů se sice uvádějí, významný je však pouze jejich počet, pořadí, typ a model volání.
Obrázek 69: Popis typu procedura
![]() |
Hodnotami procedurálních typů jsou startovací adresy uživatelských podprogramů. Vnitřním tvarem se hodnoty procedurálních typů shodují s hodnotami typů ukazatelových, formálně (z hlediska typové kontroly) však za ukazatele považovány nejsou. Kompatibilita i kompatibilita vzhledem k přiřazení je pro procedurální typy definována tak, že v jejich popisech mohou být odlišné pouze identifikátory formálních parametrů.
Následujícími deklaracemi jsou zavedeny čtyři pojmenované procedurální typy, typ PoleFunkci, jehož komponenty jsou procedurálního typu a proměnná P nepojmenovaného procedurálního typu, kompatibilního s typem Ctvrty.
Přiřazovací příkaz Pokud je na levé straně přiřazovacího příkazu uvedena proměnná procedurálního typu, může být na straně pravé buď proměnná kompatibilního procedurálního typu nebo přímo identifikátor kompatibilní procedury či funkce. Do proměnné vlevo je pak zkopírována hodnota proměnné vpravo resp. dosazena adresa uvedeného podprogramu. Podprogram, jehož adresa má být přiřazena procedurální proměnné, musí (kromě kompatibility) splňovat tyto požadavky:type Prvni = procedure; Druhy = procedure (W: Word; var R: Real); Treti = function: Real; Ctvrty = function (T: Real): Real; PoleFunkci = array [1..10] of Ctvrty; var P : function (X: Real): Real;
Poslednímu omezení se lze vyhnout deklarací uživatelského podprogramu, který volá podprogram standardní. Tímto způsobem však nelze zachovat univerzálnost některých standardních podprogramů. Následující procedura MujRead například „umí“ číst pouze jedinou celočíselnou hodnotu ze souboru Input do proměnné typu Integer.
Volání podprogramu Syntax volání podprogramu, jehož adresa je hodnotou procedurální proměnné, odpovídá syntaxi přímého volání tohoto podprogramu s tím, že jeho identifikátor je nahrazen identifikátorem procedurální proměnné.procedure MujRead (var I: Integer); far; {--------------------------------------} begin { MujRead } Read (I) end; { MujRead }
Adresní operátor @ a funkce Addr Adresní operátor @, aplikovaný na procedurální proměnnou, změní její typ na Pointer. Výsledkem operace není hodnota, nýbrž proměnná typu Pointer. Pokud je třeba získat adresu procedurální proměnné, aplikuje se dvojnásobný adresní operátor. Například @@P je ukazatel na procedurální proměnnou P. Zápis @@P již je výraz, nikoliv přístup k proměnné. Stejným způsobem lze použít i adresní funkci Addr.function Funkce (R: Real): Real; far; {-----------------------------------} begin { Funkce } if R = 0 then Funkce := 1 else Funkce := Sin(R)/R end; { Funkce } var P: function (X: Real): Real; ... P := Funkce; Writeln ('sin(0)/0 = ', P(0), 'sin(pi)/pi = ', P(Pi)); ...
Změny typu procedurálních proměnných aplikací operátoru @ lze využít k porovnávání jejich hodnot, neboť pro proměnné procedurálních typů nejsou implementovány relační operace. Za normálních okolností totiž výskyt procedurální proměnné není chápán jako proměnná, nýbrž jako volání podprogramu, který je její hodnotou. Ze stejného důvodu není možné využít ani typecasting.
Funkce Seg a Ofs Rovněž aplikace funkcí Seg a Ofs na procedurální proměnné se liší od aplikace těchto funkcí na proměnné ostatních typů. Výsledkem funkce není hodnota segmentové resp. ofsetové části adresy procedurální proměnné. Výsledkem není žádná hodnota, nýbrž proměnná — Seg (P) resp. Ofs (P) je proměnná typu Word, alokovaná ve vyšším resp. v nižším slově procedurální proměnné P. Hodnotu segmentu resp. ofsetu adresy proměnné P mají například výrazy Seg (@P) resp. Ofs (@P).if @P = @Q then ... { správně } if Pointer(P) = Pointer(Q) then... { chybně }
Procedurální parametry podprogramů Hodnoty a proměnné procedurálních typů mohou být naprosto stejně jako hodnoty a proměnné jiných typů předávány jako parametry procedurám a funkcím.
program Tabelace; {===============} type Funkce = function (X: Real): Real; { reálná funkce jedné reálné } { proměnné } procedure Tabulka (F: Funkce; X, KrokX: Real; Pocet: Byte); {---------------------------------------------------------------------} { Vytiskne tabulku funkčních hodnot funkce F pro počáteční hodnotu } { argumentu X, jeho přírustek KrokX a počet tabelovaných hodnot Pocet.} var I: Byte; { pomocná proměnná } begin { Tabulka } for I := 1 to Pocet do { cyklus řádek tabulky } begin Writeln (X:20, F(X):20); { tisk argumentu a hodnoty } X := X + KrokX { aktualizace argumentu } end { další řádka tabulky } end; { Tabulka } {$F+} function Sinus (X: Real): Real; { tabelovaná funkce } {---------------------------------------------------------------------} begin { Sinus } Sinus := Sin (X) end; { Sinus } function Cosinus (X: Real): Real; { tabelovaná funkce } {---------------------------------------------------------------------} begin { Cosinus } Cosinus := Cos (X) end; { Cosinus } {$F-} begin { program } Tabulka (Sinus, 0, Pi/4, 9); { tabulka funkce Sinus } Writeln; Tabulka (Cosinus, 0, Pi/4, 9) { tabulka funkce Cosinus } end. { program }