Type-casting aneb čáry s proměnnými

Doufám, že ovládáte bezpečně vše, co bylo řečeno v lekcích Základní typy proměnných a Struktury.

V Pascalu je hlídána tzv. typová kompatibilita. Pokusíte-li se tedy například proměnné typu Integer přiřadit Reálnou hodnotu, Pascal vám to nedovolí. Občas by se ovšem hodilo, kdyby se dala poměrně přísná pravidla Pascalu obejít.

Nejprve se podíváme na jeden typ proměnných, který jsme si ještě neuvedli.

Proměnné procedurálního typu

Tento typ umožňuje proceduře, aby se chovala jako proměnná a například vystupovala jako parametr jiné procedury či funkce.

Deklarace je jednoduchá:
type Nazev = procedure;
Nazev2 = procedure(var x:string);
Nazev3=function(I:Integer):real;

Tyto definice jsou však poněkud specifické a podléhají určitým omezením:

  1. Musí být uvedeny na nejvyšší úrovni (nesmí tedy být lokální)
  2. Do proměnné nesmíme zařadit standardní funkci (např. Write).
  3. Procedury musí být volány vzdáleně, čehož nejsnáze dosáhneme, napíšeme-li za jejich hlavičku far;
  4. Procedurální typ nemůže být použit jako návratová hodnota funkce

Příklad použití:

program proceduralni_promenne;
type BType = integer;
     TProc = function(X,Y:BType):BType;
var proc : TProc;

function Nasob(X,Y:BType):BType;far;
begin
 Nasob:=X*Y;
end;

function Secti(X,Y:BType):BType;far;
begin
 Secti:=X+Y;
end;

procedure Vypis(Func:TProc;XOd,YOd,XDo,YDo:Integer);
var I,J:integer;
begin
 write('          ');
 for i:=XOd to XDo do
  write(i:5);
 writeln;writeln;
 for J:=YOd to YDo do
  begin
   write(J:5);
   write('     ');
   for I:=XOd to XDo do
    write(Func(I,J):5);
   writeln;
  end;
end;

begin
 proc:=Secti;
 Vypis(proc,0,0,10,10);
 writeln;writeln;
 Vypis(nasob,0,0,10,10);
 readln;
end.

Typová kompatibilita

Nyní se seznamme s pravidly, která později budeme chtít obcházet.
Typy proměnných jsou identické:

Typy proměnných jsou kompatibilní:

Proměnou typu T1 lze přiřadit proměnné typu T2 (T2 := T1), jestliže

Tedy například:

var C: 1..7;
             D: 1..7;
Typy proměnných C a D nejsou identické!!!
type Interval= 1..7;
var
A:Interval;
B:Interval;
Zde už je A i B identického typu. (Ale A není identického typu s C ani D...)

Type-casting

Tak to by byla teorie a nyní se podívejme, jak ji obejít :

Do videopaměti lze tedy přistupovat takto :

var Text : array [1..25,1..80] of
 record
  Pismeno : char;
  Barva : Byte;
 end absolute $B000:$0000;

Změníme-li nyní například Text[20,11].Pismeno na 'b', objeví se na obrazovce na příslušném řádku písmeno b...Stejně tak můžeme z takto nadefinované proměnné číst, jaká jsou písmena na obrazovce.

Použití direktivy absolute je většinou nevhodné, na jiném počítači mohou být data reprezentována jinak a náš program se pak stává nepřenositelný. Pokud se přesto nedokážeme bez této direktivy obejít, je nejlepší veškeré její výskyty umístit do jediné malé unity (a v hlavním programu volat příslušné funkce z ní). Malá unita půjde změnit snadno.

Dcv : Napište alespoň šest programů, kde využijete typové změny proměnné a pokuste se najít další způsoby, jak využít direktivu absolute. Napište alespoň dva programy na každý její možný způsob využití.

Ve třetí části se podíváme na bitové operace.

Nejmenší jednotkou informace je jeden bit. Ten může nabývat pouze dvou hodnot (0, I). Několika bitů dohromady pak může vyjadřovat mnohem větší množství informace (např. celou abecedu)

Celá čísla jsou v Pascalu reprezentována svou hodnotou v dvojkové soustavě (nevíte-li, co to je, tak to koukejte honem rychle zjistit!!!). A převádět čísla mezi binární, osmičkovou a hexadecimální se naučte zpaměti (1111B = 17O = FH (někdy také $F) = 15D).
I znaky jsou reprezentovány svojí ASCII hodnotou (pochopitelně v binární soustavě).

Některé operace je lepší provádět přímo na bitové úrovni. Pro tyto operace Pascal definuje tzv. bitové operátory.

operátor operace
not bitová negace
and bitový součin
or bitový součet
xor exkluzivní bitový součet
shr bitový posun doprava
shl bitový posun doleva

Operátor NOT je unární - potřebuje k sobě pouze jedinou proměnnou. Všechny její bity změní na opačné (1 -->0, 0-->1)

X AND Y znásobí mezi sebou jednotlivé bity (1.bit X a 1.bit Y...)
X OR Y příslušné bity sečte (při tomto sčítání ale platí, že 1 + 1 = 1)
X XOR Y příslušné bity exkluzivně sečte (tady platí, že 1 + 1 = 0)

Zkuste si teď sami vymyslet postup, který prohodí obsah dvou proměnných, aniž by využil jakékoliv pomocné proměnné.

Je to jednoduché a šetří to paměť (ale tento trik funguje jen u některých typů proměnných):
A:=A xor B;
B:=A xor B;
A:=A xor B;

Zbývají nám poslední dva operátory - shl a shr. Ty posouvají jednotlivé bity o n znaků doleva (resp. doprava). Přebytečné bity se ztrácejí, z druhé strany jsou pak doplňovány nuly.

Tedy 10010101 shr 1 = 01001010 a naproti tomu 10010101 shl 1 = 00101010

Těmito operátory lze nahradit celočíselné dělení, popř. násobení dvěma a mocninami dvojky (vzpomeňte si, jak dělíme v desítkové soustavě deseti, není to obdobné?)

V praxi to vypadá takto (lze používat libovolné mocniny n)
235 shr 2 = 58
1 shr 3 = 8

To by bylo pro dnešek vše.