Kurs programování "C" část 6.

©=37,/=92,}=123,(=91,)=93,"=39,B=38

definice znaku procenta, obráceného lomítka, levé složené závorky, levé a pravé lomené závorky, apostrofu.

a nově znaku and

Hodnoty a druhy proměnných I

Snažil jsem se získat trochu přehled o používaných proměnných naším Céčkem, ale to se mi nepodařilo. Prohlédnutím originálního popisu v angličtině jsem se přesvědčil, že v překladu nic důležitého nechybí, i když jsou v něm strašné věci vinou doslovných překladů.

Normální Céčka používají několik druhů proměnných. Typ char je vždy jednobajtový. Číselné typy jsou minimálně dvoubajtové, a to jako celá čísla nebo s desetinnou tečkou různých délek. Char a celočíselné, čili int mohou být bez znaménka, nebo znaménkové, tedy jejich hodnoty mohou být i záporné. Jejich rozlišení se provádí modifikátory signed a unsigned. Naše Céčko nemá přesně popsané druhy proměnných, pokud se k originálním verzím nedodával manuál tištěný. Podle zkušeností lze usoudit, že znaménkové modifikátory odmítá. Typ char je braný jako neznaménkový v hodnotách 0 - 255. Typ int je dvoubajtový a tiskne se jako znaménkový. Tedy v hodnotách -32768 až +32767. Přesto se někdy chová jako neznaménkový, čili s hodnotami 0 až 65535. Konkrétně v uvedeném programu se používá na "poukování" paměti v oblasti její horní poloviny. Tuto anomálii zatím vysvětlit nemůžu.

Z hlediska umístění v paměti jsou proměnné lokální a globální. Mají několik variací, které zatím nejsou důležité.

Lokální jsou viditelné jen ve funkci, v níž byly deklarované. Jejich adresa se může předávat funkcím volaným. Po opuštění běhu funkce se likvidují, protože jsou umístěny v paměti typu zásobník, která se při návratu uvolní. Tento systém práce přirozeně omezuje jejich maximální velikost. V našich odkladech údaj o horní hranici chybí, nebo jsem ho přehlédl. Je jisto, že proměnná pro uložení obrázku několikanásobně překročila hranici pro Céčko na ST, i když to podle příručky mělo jít. Na malém ATARI jsem ji ani jako lokální deklarovat nezkoušel.

Globální proměnné jsou deklarovány vně funkcí, takže je mohou všechny používat, nebo přesněji ty od místa deklarace proměnné. Jejich maximání délka nebude mít takové problémy jako lokální, ale přesný údaj mi opět chybí.

Pointery a adresové operátory II

Minule jsem se zmiňoval o vlastnosti jména řetězcové proměnné. Totiž že samo je ukazatelem na řetězec, proto se u něj nepoužívá adresový operátor. To můžete názorně vidět na funkcích gets() nebo strcpy(), jimž se předá pouze samotný název. Neplatí to ale u standartní funkce scanf(), u níž je operátor B třeba. Vysvětlit se to asi nedá, prostě to tak je.

Ještě musím poznamenat, že pojem řetězec je nevhodně zvolený. Správně jsem měl psát pole, protože řetězec je sice pole, ale ne každé pole je řetězec.

Užití pointeru jako náhradu příkazů PEEK a POKE je velmi snadné. Pointery se prostě deklarují jako typ char. To znamená, že budou ukazovat na proměnné velikosti jednoho bajtu, což je přesně jedno pamětové místo. Samotný pointer má hodnotu větší, protože musí adresově obsáhnout celou paměť. (Zřejmě je typu int, protože takový jsem bez problémů použil při předávání pointeru volané funkci v jednom rozpracovaném programu.).

Po deklaraci stačí pointeru přiřadit žádanou fyzickou adresu a již se může číst, nebo zapisovat. Vypadá to tak:

    char *p_adr;
    p_adr = 708;
    *p_adr = 4;

nebo místo posledního řádku:

    p_adr(708) = 4;

Zde by došlo k nastavení jednoho z barvových registrů.

Bitové operace I

Jazyk C umožňuje přímé bitové operace s hodnotami proměnných. Některé verze jen s neznaménkovanými, jiné i se znaménkovými čísly. Nejpřehlednější je samozřejmě toto dělat s jednobajtovými hodnotami.

Seznam operátorů:

   B (znak and) bitový součin    AND
   |            bitový součet    OR
 stříška    exklusívní součet    XOR
  <<            posun doleva
  >>            posun doprava
 vlnovka        jedničkový doplněk

V přiloženém programu jsou použity bitový součin pro vymaskování potřebného bitu z celého bajtu. Dále bitové posuny, jinak také rotace.

Počet posunů určuje parametr uvedený za operátorem.

Výraz x<<4 dá hodnotu, v níž je původní obsah proměnné x posunut o čtyři bity doleva. X zůstane zde beze změny. Tak je to využito v hardkopírce. Pokud by se měl obsah x změnit, musel by se z výrazu stát tento příkaz:

  x=x<<4; nebo také x<<=4;.

Popis programu Harkopírka.

Ke kursu je přiložen dvojí výpis programu v provedení pro malé ATARI a pro 16 bitové počítače. Řeším tím částečně dotaz z minule na tisk obrázků na PC. Při jeho případném přenosu nezapoměňte zvolit konverzi Returnu na standartní konec odstavce CR a LF.

Nejdříve tedy jak je to s přenositelností programů mezi počítači. Bez problémů jsou základní věci nepoužívájící speciality jednotlivých typů počítačů. Tedy standartní vstupy a výstupy z klávesnice a na obrazovku.

Uváděný program byl v základním stavu odladěn na ATARI ST, dopracování dalších funkcí již probíhalo zvlášť. Prvním rozdílem je použití povelů include<> a deklarací funkcí definovaných přímo v programu. Příkaz preprocesoru include<> ukazuje na soubory s deklaracemi knihovnických funkcí. Ono by to zaše šlo bez toho, ale s nejistým výsledkem. Tyto záležitosti se při přenosu na malé ATARI umažou.

V definicích funkcí jsou uváděny typy parametrů funkci předávaných a návratové hodnoty. Stačí opět zrušit.

Ukazovátko na otevíraný soubor je typu pointer (z nejasných důvodů). U nás se použije obyčejný typ int, protože nepodařený pokus o otevření (zavření) souboru vrací zápornou hodnotu.

Některé stejné příkazy se jmenují trochu jinak, jako cputc, copen. Funkce scanf(), použitá pro zadání číselných hodnot, nám chybí. Proto je nahrazena čtením řetězce s následným převodem na číslo.

Po těchto, zjevně minimálních úpravách, se mi program rozeběhnul i na malém ATARI. Oproti verzi "16-cti bitové" je v něm dodatečně doděláno několik specialit. Především je nastaven grafický monochromatický mód a obrázek je přímo uložen do videoram. Tištěná data se můžou posílat i do souboru. To je vlastně dáno jednotným způsobem otevírání různých zařízení, na tom nebylo třeba nic složitě vymýšlet.

Přidána byla funkce výpisu obsahu disku. Tak jak je, může být použita i u jiných programů, pokud nebude vadit, že si natvrdo otevírá kanál č.5. Normální funkce copen() si sama najde volný kanál, ale tu není možné použít pro adresář. Proto je využita funkce open().

Pozměněná je logika odřádkování pro dvojprůchodový tisk, protože se předpokládá na tiskárně nastavené automatické odřádkování. Proto je vysílán povel inverzního posunu válce.

Na "velké" verzi je doděláno jen přímé načtení celého obrázku naráz. (Příště to udělám i na malém ATARI.) Zato nemá výpis adresáře a načíst obrázky může jen z adresáře, z něhož je spouštěna.

Většina nových jevů vyskytujících se v programu je vysvětlena v textu kursu. Mimo to obsahuje výpis ještě definici řetězcových konstant v úvodu programu a volání funkce pro nastavení grafického módu. Ta vrací hlášení o proběhlé operaci, které sice ukládám do proměnné ale bez dalšího využití.

Volby menu se provádí zadáváním písmenem, které může být velké i malé, pouze návrat musí být potvrzen jenom velkým znakem.

Při psaní programu jsem udělal spoustu chyb, z nichž základní byly nadeklarování proměnných o jedno místo kratší a napsání výrazu x/2 místo x/=2, takže sice docházelo k výpočtu, ale výsledek se neukládal zpět do proměnné.

Z doby odladování programu zůstala kontrola počtu zpracovaných dat ve funkci hardcopy(), konkrétně řádek IF(e>7680). Teď už je zbytečný, protože kdyby skutečně došlo k přetečení proměnné, tak příkaz return; ukončí činnost funkce. To se neděje, ale stejně likvidace podmínky způsobí vytuhnutí při chodu a já nevím proč. Je to případ programu žijícího si svou vlastní inteligencí nezávisle na svém tvůrci.

-ZB-