Prístup k jednej premennej z viacerými typmi deklarácie
Keď mám takúto definíciu premennej
var xy: array[0..7, 0..7] of Integer;
a chcem k nej pristupovať aj ako
var xy: array[0..63] of Integer;
tak mám na výber dve možnosti:
1.
var
xy1: array[0..7, 0..7] of Integer;
xy2: array[0..63] of Integer absolute xy1;
2.
var
xy: record
case Byte of
1: a: array[0..7, 0..7] of Integer;
2: b: array[0..63] of Integer;
end;
end;
Vie mi niekto vysvetliť, načo je dobrá druhá definícia a v čom je výhodnejšia? Prvá definícia je použiteľná v TP a myslím aj v Delphi. Overené nemám. A zaujímalo by ma hlavne toto:
1. Čo znamená Byte v case? Prečo tam nie je Word alebo niečo iné? Načo to tam vôbec je?
2. Čo znamenajú tie čísla vo vetvení case?
Viem o čo sa jedná, ale nechápem tomu vetveniu, prečo to nejde napísať nejako takto (môj výmysel):
var
xy: record
switch
a: array[0..7, 0..7] of Integer;
b: array[0..63] of Integer;
end;
end;
Na frázi absolute zapomeň, neměla by se používat je-li vyhnutí.
Ve standardním pascalu by to mělo vypadat takto:
Pak je jasné, proč jsou v CASE čísla větvení. Prostě jakou hodnotu obsahovalo CoToJe, taková větev deklarace se vybrala. Protože se ve skutečnosti jedná o redefinici téhož místa paměti, DELPHI dovoluje zjednodušení na uvedení jen typu a hodnot. Lze to třeba taky takto:
Že to nejde přes switch je dáno syntaxí jazyka.
Doporučuji, sežeň si někde knížku "Delphi v kostce" z O'Reilly (česky vydal Computer press), tam najdeš odpovědi na většinu tvých dotazů (to neznamená, že bych nechtěl odpovídat, jen bys to měl takříkajíc při ruce ).
PS: V redefinicích doporučuju použít packed record, aby se tam někde nenacpaly výplňové bajty pro zaokrouhlení adres.
1. Tak toto je potom čo? Z jedného šachového programu:
Pri deklarácii sa tá deliaca premenná pre case nikde nedefinuje.
2. Pokiaľ viem, vraj v Turbo Pascale stratilo slovo packet význam. Stačí použiť direktívu na vypnutie Word align data $A- a je to. V Delphi je to obdobné.
1: Jak jsem napsal výše: Delphi dovoluje zjednodušení (o proti standardnímu Pascalu - ten to nedovoluje), že místo řídící proměnné záznamu stačí uvést jen její typ. Programátor pak musí sám rozhodnout (v programu), kdy a jak bude danou část paměti interpretovat. Například součástí unity SysUtils je následující definice:
Typem WordRec můeme dle libosti interpretovat hodnotu typu word jako její horní bajt Hi a dolní bajt Lo nebo jako pole bajtů Bytes [0] a Bytes [1]. V SysUtils najdeš ještě další užitečné redefinice, například: LongRec a Int64Rec.
//Edit: V tebou uvedené deklaraci může programátor dle libosti, chutě a podle toho, jak se mu který algoritmus lépe dělá interpretovat šachovnici jako:
yx - dvourozměrné pole 8x16 s bajtovou hodnotou, indexováno yx [y, x] nebo:
yxs - dvourozměrné pole 8x16 s ShortInt hodnotou, indexováno yxs [y, x] a konečně nebo:
r - jednorozměrné pole 128 bajtů furt za sebou, indexováno r [x] ...
Jedná se ale furt o totéž místo paměti, takže výrazy: yx [1, 0], yxs [1, 0], r [16] označují furt jeden a tentýž bajt.
(Proč však má šachovnici 8x16 to nevím )
2. Packed mělo a má stále význam a to, že v záznamu nebudou generovány výplňkové bajty. Narozdíl od standartního Pascalu, kde packed určuje komprimovaný způsob uložení. Slovo packed v record je IMHO (Jez.) názornější, než direktiva $A-. Navíc direktiva $A- zatrhne výpňkové bajty na celou junitu, což rozhodně není žádoucí. Leda furt uvádět $A- a pak $A+.
Napisem len nieco vseobecne: toto co robis je IMHO vseobecne nie moc dobra praktika, ptz si nemozes byt isty ako bude reprezentovat dvojrozmerne pole nejaky (neznamy) prekladac (bude najprv prvy rozmer alebo druhy rozmer, bude tam alignment, apod). Ja viem ze standard je jasny a bude ti to fungovat na tom tvojom prekladaci, ale je to proste IMHO "spinave". Aj pouzivat absolutne cisla v programe je nevhodny zvyk, kvoli citatelnosti programu a kvoli lahkej zmene v buducnosti je vhodne pouzivat vopred definovane symboly(nazvy) namiesto cisel.
V C je na to o co sa snazis union, ale IMHO je bezpecnejsie zadefinovanie pola len raz ostatne pristupy robit napr. cez makro. Ja by som to urobil napr. takto (pouzijem syntax C):
#define SIRKA_SACHOVNICE 8
#define VYSKA_SACHOVNICE 8
int Sachovnica[SIRKA_SACHOVNICE * VYSKA_SACHOVNICE]; // toto je jedina definicia
#define SachovnicaXY(x,y) Sachovnica[x + y*SIRKA_SACHOVNICE]
A som si vzdy (na vsetkych prekladacoch a s akymkolvek nastavenim) isty ze co mam kde ulozene, a je to aj citatelnejsie a rozmer je lahko zmenitelny (asi ho nikto menit nebude ale ide mi vseobecne aj o ine cisla).
Pristup cez x,y cez to nasobenie moze byt menej efektivny (nie som si zhlavy isty ako preklada pristup na dvojrozmerne pole cez [x,y] na instrukcie CPU ci na to nie je efektivnejsia instrukcia ako nasobenie a scitanie)