.pl 60 .po 12 .mt 2 .mb 2 .pn 185 11. Pravidla rozsahu platnosti ------------------------------- Program v C jazyku nemusi byt kompilovan najednou v celku. Zdrojovy text programu muze byt ulozen v nekolika souborech a predem prelozene programy mohou byt pripojeny z knihoven. Ko- munikace mezi funkcemi programu se muze uskutecnit pomoci funk- cnich volani nebo pomoci externich dat. Existuji dva pohledy na pojem rozsahu platnosti. Prvni z nich urcuje lexikalni rozsah platnosti identifikatoru. Ktery by mohl byt intuitivne chapan jako usek programu, ve kterem muze byt tento identifikator pouzit, aniz dojde k chybe "nede- finovany identifikator". Druhy pohled je spojen s pouzitim ex- ternich identifikatoru, ktere jsou charakterizovany pravidlem, ktere tvrdi, ze totozne externi identifikatory urcuji tytez objekty. 11.1 Lexikalni rozsah platnosti -------------------------------- Lexikalni rozsah platnosti externich identifikatoru je od mista jejich definice do konce souboru ve kterem jsou definova- ny. Lexikalni rozsah formalnich parametru je funkce, ve ktere jsou definovany. Lexikalni rozsah identifkatoru definovanych na pocatku bloku je od mista jejich definovani do konce bloku. Lexikalni rozsah navesti je cela funkce, ve ktere jsou defino- vana. Protoze vsechny odkazy na tentyz externi identifikator musi urcovat tentyz objekt /viz odstavec c. 11.2/, prekladac kontro- luje vsechny deklarace tehoz externiho identifkatoru na kompa- tibilitu. Vysledkem je pak rozsah platnosti takoveho identifi- katoru po celem souboru, ve ktere se jeho deklarace vyskytuji. Dale plati nasledujici pravidlo. Jestlize je nejaky identi- fikator deklarovan na pocatku bloku, vcetne bloku tvoriciho definici funkce, jakakoliv deklarace tehoz identifikatoru vne tohoto bloku je potlacena do konce daneho bloku. Je nutne pripomenout /viz odstavec c. 8.5/, ze identifika- tor prirazeny skutecne promenne a identifikator prirazeny polozce struktury nebo unionu ci znacce struktury nebo unionu patri do dvou ruz- nych trid, ktere jsou bezkonfliktni. Pro polozky a znacky struktur a unionu plati stejna pravidla rozsahu jako pro osta- tni identifikatory. Mohou byt znovu deklarovany ve vnitrnim bloku, ale musi byt pri nove deklaraci explicitne uveden typ. TYPEDEF FLOAT distance; ... { AUTO INT distance; ... Ve vyse uvedenem prikladu musi byt ve druhe definici explicit- ne uveden typ int, jinak by tato definice byla pochopena jako definice bez deklaratoru a s typem distance. Je nutne priznat, ze tato vlastnost jazyka je ponekud problematicka. Š.po 3 11.2 Rozsah platnosti externich promennych ------------------------------------------- Jestlize funkce pouziva identifikator, ktery je deklarovan jako EXTERN, musi byt tento identifikator jako externi dekla- rovan v nekterem souboru nebo knihovne ze kterych je vytvoren kompletni program. Vsechny funkce, ktere pracuji s timze exter- nim identifikatorem pracuji s timze objektem, musi byt tedy zajisteno, ze typ a velikost dana definici identifikatoru je kompatibilni s typem a velikosti specifikovane ve vsech funk- cich, ktere tento identifikator pouzivaji. Vyskyt klicoveho slova EXTERN v externi definici znamena, ze pametove misto pro danou promennou, ktera je deklarovana, bude rezervovano jinou casti programu, ktera je umistena v ji- nem souboru. Program, ktery je slozen z vice casti, ktere jsou umisteny v samostatnych souborech, musi obsahovat pouze jedi- nou definici externich dat bez klicoveho slova EXTERN. V ostat- nich souborech, ve kterych ma byt dana externi definice, musi byt v ni uvedeno klicove slovo EXTERN. Identifikatory, ktere jsou deklarovany na vnejsi urovni pro- gramu s klicovym slovem STATIC, nejsou z ostatnich souboru pri- stupne. Se specifikaci STATIC smeji byt deklarovany i funkce. 12. Ridici radky prekladace --------------------------- Prekladac jazyka C obsahuje prekladac schopny makrosubstice, podmineneho prekladu a zacleneni "include" souboru. Radky, ktere pocinaji znakem "#", ridi cinnost tohoto predprekladace. Tyto radky maji syntaxi nezavislou na syntaxi jazyka C. Mohou se vyskytovat kdekoliv v programu a jejich ucinek je od radky, ktera je nasleduje az do konce programu. 12.1 Zamena syntakticke jednotky --------------------------------- Ridici radka predprekladace ma nasledujici tvar: #DEFINE identifikator retezec_syntaktickych_jednotek Radka nemusi byt ukoncena strednikem. Tato direktiva zpusobi, ze kazdy vyskyt identifikatoru v programu bude nahrazen retez- cem syntaktickych jednotek. Radka muze mit alternativni formu: #DEFINE identifikator(identifikator, ...,identifikator)rete- zec_syn._jedn. Nesmi byt mezera mezi prvnim identifikatorem a znakem "(". V tom pripade se jedna o definici makra s argumenty. Rada polo- zek, ktera se sklada s prvniho identifikatoru, leve zavorky, seznamu syntaktickych polozek oddelenych carkami a prave za- vorky je nahrazena retezcem syntaktickych polozek z ridici rad- ky. Pri tom je kazdy vyskyt identifikatoru v seznamu formalnich parametru v definici nahrazen odpovidajici syntaktickou poloz- kou pouzitou pri vyvolani makra. Skutecne argumenty pri vyvola- Š.po 12 ni makra jsou retezce syntaktickych jednotek oddelenych carka- mi. Carky, ktere se vyskytuji v retezci uzavrenych mezi uvozov- ky, neoddeluji argumenty. Pocet formalnich a skutecnych argu- mentu musi byt tentyz. Texty uvnitr retezcu nebo znakove kon- stanty nejsou nahrazovany. Pri obou formach je retezec po zamene znovu zpracovan pred- prekladacem. Dlouhe definice mohou pokracovat na nasledujici radce, jestlize se predchazejici radka ukonci znakem "\". Tato schopnost prekladace je velmi vyhodna pri definici casto pouzivanych konstant, jako napriklad: #DEFINE tabsize 100 INT table[tabsize]; Ridici radka, ktera ma nasledujici formu: #UNDEF identifikator zpusobi, ze predesla definice identifikatoru pomoci ridici rad- ky #DEFINE bude prekladacem zapomenuta. 12.2 Vkladani souboru ---------------------- Ridici radka, ktera ma nasledujici tvar: #INCLUDE "nazev_souboru" zpusobi nahrazeni teto radky obsahem souboru, jehoz nazev je nazev_souboru. Tento soubor je nejprve hledan v adresari, ve kterem je umisten zdrojovy soubor, ktery je prave prekladan. Pokud neni v tomto adresari nalezen, je postupne hledan v dal- sich standartnich adresarich . Existuje alternativni forma te- to ridici radky, ktera ma nasledujici tvar: #INCLUDE V tomto pripade jsou prohledavany pouze standartni adresare a neni prohledavan adresar ve kterem je umisten zdrojovy soubor. "Include" soubor muze obsahovat dalsi prikaz INCLUDE. 12.3 Podminena kompilace ------------------------- Ridici radka prekladace, ktera ma nasledujici tvar: #IF konstantni_vyraz Jestlize kontrolovana podminka je pravdiva, jsou radky mezi ridicimi radkami #ELSE a #ENDIF ignorovany. Jestlize kontro- lovana podminka je nepravdiva, jsou ignorovany radky mezi rad- kou obsahujici test a radkou s ridicim prikazem #ELSE, nebo jestlize neni radka #ELSE uvedena, radkou obsahujici ridici prikaz #ENDIF. Pouziti techto konstrukci muze byt vnorene. Š.po 3 12.4 Rizeni radkovani ---------------------- Pro pouziti s ostatnimi predprekladaci, ktere mohou genero- vyt program v jazyku C, je zavedena ridici radka ve tvaru: #LINE konstanta identifikator??? Tato radka zpusobi, ze prekladac bude predpokladat, ze cislo nasledujici radky ve zdrojovem souboru je rovno konstante uve- dene v ridicim prikazu LINE, a zapocne od teto hodnoty dalsi radky cislovat. Toto je uzitecne napriklad z duvodu diagnostiky chyb. Pokud je uveden i identifikator, bude predpokladat, ze nazev zdrojoveho souboru je totozny se jmenem tohoto identifi- katoru. 13. Implicitni deklarace ------------------------ Neni vzdy nutne specifikovat jak tridu ulozeni tak typ iden- tifikatoru v deklaraci. Trida ulozeni je dana kontextem pri externi definici a pri deklaracich formalnich parametru a polo- zek struktur. Pri deklaracich uvnitr funkci plati nasledujici pravidla: - je dana trida ulozeni, ale neni dan typ, potom se predpoklada typ INT - je dan typ, ale neni dana trida ulozeni, potom se predpoklada trida AUTO - vyjimkou z druheho pravidla je deklarace funkci, protoze fun- kce tridy AUTO nemohou existovat /jazyk C neni schopen kompi- lace vykonatelneho kodu do zasobniku/ - jestlize typ identifikatoru je "function returning ..." je implicitne deklarovan jako EXTERN Pokud se ve vyrazech vyskytne identifikator, ktery neni jeste deklarovan a je nasledovan levou zavorkou, je kontextove dekla- rovan jako "function returning int". 14. Dalsi informace o typech ---------------------------- V teto casti budou shrnuty operace, ktere je mozne uskutec- novat na objektech ruznych typu. 14.1 Struktury a uniony ----------------------- Jsou dovoleny pouze dve operace, ktere je mozne uskutecnit s objekty, ktere maji typ struktury: - pristup k jedne z jeho polozek pomoci operatoru ".". - ziskani adresy dane struktury pomoci operatoru "&". Jine operace jako je napriklad prirazeni nebo pouziti jako argument funkce zpusobi chybovou zpravu. Je mozne ocekavat, ze pri budoucich rozsirenich jazyka budou takove operace nebo nektere z nich dovoleny. V odstavci c. 7 je definovano, ze pri primem nebo neprimem pristupu do struktur / pomoci operatoru "." nebo "->"/ musi Š.po 12 byt clen na prave strane polozkou struktury a clen na strane leve bud nazev struktury nebo ukazovatko na takovou strukturu. Aby bylo mozne zmenit vyse uvedene pravidlo, neni prekladacem provadena dusledna kontrola tohoto pravidla. Ve skutecnosti muze byt na leve strane od operatoru "." libovolna lhodnota, ktera ma tvar struktury a na prave strane nazev polozky teto struktury. Take na leve strane od operatoru "->" muze byt uve- den libovolny vyraz, ktery ma tvar ukazovatka nebo celeho cis- la. Jestlize se jedna o ukazovatko, predpoklada se, ze ukazuje na strukturu a nazev jedne polozky teto struktury je uveden na prave strane operatoru. Jestlize je na leve strane uveden vyraz typu int, je chapan jako absolutni adresa v pameti pocitace, kde je dana struktura umistena. Je nutne poznamenat, ze takove konstrukce mohou byt neprenositelne. 14.2 Funkce ----------- Jsou dovoleny pouze dve operace, ktere je mozne uskutecnit s objekty charakteru funkce: - vyvolani funkce - ziskani adresy vstupniho bodu funkce Jestlize se nazev funkce vyskytne ve vyrazu, ale nikoliv ve tvaru vyvolani teto funkce, je chapan jako ukazovatko na tuto funkci. Je tedy mozne pouzit nazev funkce jako argument pri vyvolani jine funkce, napriklad: INT f(); ... g(f); Funkce g muze byt definovana nasledovne: g(funcp) INT(*funcp)(); { ... (*funcp)(); ... } Poznamenavame, ze funkce f musi byt deklarovana explicitne ve vyvolavajici casti programu, protoze nazev funkce f neni pri vyvolani nasledovan levou zavorkou. 14.3 Pole, ukazovatka a indexy ------------------------------ Kdykoliv se ve vyrazu objevi identifikator pole, je konver- tovan na ukazovatko ukazujici na prvni polozku tohoto pole. Ta- to konverze je nutna, protoze pole nejsou l-hodnotami. Podle definice je operator indexu "[]" interpretovan takovym zpuso- bem, ze vyraz E1[E2] je totozny s vyrazem *((E1) + (E2)). Jestlize E1 je pole a E2 cele cislo, potom tyto vyrazy urcuji E2 polozku pole E1. Indexovani je komutativni operace. Š.po 3 Podobna pravidla plati i pro vicerozmerna pole. Jestlize E je n-rozmerne pole velikosti i x j x ... x k, potom je iden- tifikator E vyskytujici se ve vyrazu konvertovan na ukazovatko ukazujici na (n-1) -rozmerne pole o velikosti j x ... x k. Jestlize je potom operator "&", at uz vyjadreny explicitne nebo implicitne jako vysledek indexovani, pouzit s takovym ukazovat- kem, vysledek bude ukazovat na (n-1) -rozmerne pole, a bude okamzite konvertovan na ukazovatko. Uvedeme priklad: INT x[3][5]; V tomto pripadu se jedna o pole velikosti 3x5 s polozkami typu int. Pokud se identifikator x objevi ve vyrazu, je konvertovan na ukazovatko, ktere ukazuje na prvni polozku /prvni ze tri/, kterou je pole obsahujici 5 clenu typu int. Ve vyrazu x[i], ktery je ekvivalentni vyrazu *(x+i), je identifikator x nejprve konvertovan na ukazovatko, jak bylo jiz vyse popsano a potom je index i konvertovan na typ objektu x, coz znamena ze i je naso- beno delkou objektu, na ktery ukazuje vyse zminene ukazovatko, tzn. na objekt obsahujici 5 objektu typu int. Vysledek je pri- cten k ukazovatku. Timto zpusobem je neprimo urceno pole /o5-ti celociselnych polozkach/, ktere je opet chapano jako ukazovat- ko na prvni jeho polozku. Jestlize se tentyz argument pouzije na dalsi index, vyse zminena pravidla budou pouzita znovu. Vy- sledkem bude ale objekt typu int. Nasledek vsech vyse uvedenych pravidel je ten, ze pole v jazy- ku C jsou ukladana po radkach a posledni index se meni nejrych- leji. Prvni index se podili na urceni velikosti pole, ale nepo- dili se na indexovych vypoctech. 14.4 Explicitni konverze ukazovatek ----------------------------------- Nektere konverze ukazovatek jsou sice dovoleny, ale jsou za- visle na implementaci jazyka. Takove konverze jsou specifikova- ny pomoci explicitniho operatoru typu konverze, viz. odstavec c. 7.2 a 8.7. Ukazovatko muze byt konvertovano na libovolny celociselny typ, ktery ma vhodnou velikost. Je zavisle na technickych pro- stredcich systemu, jestli bude vyzadovan typ int nebo long. Mapovaci funkce je take zavisla na technickem vybaveni, ale ne- mela by byt neobvykla pro uzivatele, kteri jsou obeznameni s adresni strukturou vypocetniho systemu. Nektere podrobnosti pro vyse jiz zminene vypocetni systemy budou uvedeny dale. Objekty celociselnych typu mohou byt konvertovany na ukazo- vatka. Mapovaci funkce by mela zajistit, aby cele cislo ziskane konverzi ukazovatka zpetnou konverzi poskytlo totozne ukazovat- ko. Jinak je ovsem zpusob mapovani zcela zavisly na technickych prostredcich systemu. Ukazovatko na objekt jednoho typu smi byt konvertovano na ukazovatko na objekt jineho typu. Pri pouziti vysledneho ukazo- vatka mouhou vzniknout chyby, pokud se nejedna o primerene objekty. Musi byt zaruceno, ze ukazovatko na objekt dane veli- kosti muze byt konvertovano na objekt v mensi velikosti a zpet beze zmeny. Napriklad, funkce pro pridelovani pameti prijima jeden argu- Š.po 12 ment, ktery urcuje velikost objektu, kteremu ma byt pridelena pamet /ve slabikach/ a vraci ukazovatko na typ CHAR. Tato funkce muze byt pouzita nasledujicim zpusobem: EXTERN CHAR *ALLOC(); DOUBLE *DP; DP = (DOUBLE*)ALLOC(SIZEOF(DOUBLE)); *DP = 22.0/7.0; Funkce ALLOC musi zajistik technickymi prostredky systemu, ze hodnota, kterou vraci, je vhodna pro konverzi na ukazovatko na objekt typu DOUBLE, potom je pouziti takove funkce prenositel- ne. Reprezentace ukazovatek na systemu PDP-11 koresponduje 16-ti bitovymi celymi cisly a zakladni jednotkou jsou slabiky /byte/. Objekty typu CHAR mohou byt ukladany na libovolne adresy, ostatni objekty musi byt ukladany na sude adresy. Na systemu Honeywell 6000 ukazovatka koresponduji s 36-ti bitovymi celymi cisly. Slovo je ulozeno v levych 18 bitech a dalsi dva bity jsou urceny k vyberu znaku ze slova, ktere lezi nalevo. Zakladni jednotka pro ukazovatka na objekty typu CHAR ma rozsah 2**16 slabik, zakladni jednotka pro ukazovatka na zbyvajici objekty ma rozsah 2**18 strojnich slov. Objekty typu DOUBLE a agregaty, ktere takove objekty obsahuji, musi byt ulo- zeny na sudych adresach pocitanych ve slovach /mod 2**19/. Systemy IBM 370 a Interdata 8/32 jsou si podobne. Na obou systemech jsou zakladni jednotkou slabiky. Zakladni objekty musi byt ulozeny na adresy, ktere odpovidaji jejich delce. Takze ukazovatka na objekty typu SHORT musi splnit podminku 0 mod 2, objekty typu INT a FLOAT 0 mod 4 a objekty typu DOUBLE 0 mod 8. Agregaty jsou umisteny tak, aby jejich umisteni vyho- vovalo vsem jejich polozkam. 15. Konstantni vyrazy --------------------- V nekterych pripadech je pozadovano, aby vysledkem nejakeho vyrazu byla konstanta. Napriklad po prikazu CASE, jako veli- kost poli a pri inicializaci. V prvnich dvou pripadech takovy vyraz muze obsahovat pouze celociselnou konstantu, znakovou konstantu a operator SIZEOF, ktere mohou byt spojeny nasleduji- cimi binarnimi operatory: + - * / % & \ << >> =x != < > <= >= nebo unarnim operatorem: - nebo ternarnim operatorem: ? : Ve vyrazu mohou byt pouzity zavorky, ale nikoliv funkcni vola- ni. Vetsi moznosti jsou dovoleny pri inicializaci. Mimo konstan- tnich vyrazu, tak jak je uvedeno vyse je mozne pouzit unarniho operatoru "&" na objekty typu EXTERN nebo STATIC nebo na pole typu EXTERN nebo STATIC s indexem, ktery je dan konstantnim vy- razem. Unarni operator "&" muze byt take pouzit implicitne, tim Š.po 3 ze je uveden nazev pole bez indexu ci nazev funkce. Zakladni pravidlo je nasledujici: vyhodnoceny vyraz musi byt bud kon- stanta nebo adresa jiz drive deklarovane objektu typu EXTERN ci STATIC, ke ktere muze byt prictena nebo odectena konstanta. 16. Uvahy o prenositelnosti --------------------------- Nektere aspekty jazyka C jsou zavisle na technickych pro- stredcich. Nasledujici vyklad nekterych potizi z toho vyply- vajicich si necini narok na uplnost, ale naznaci nejdulezitejsi z nich. Ciste technicke problemy jako je velikost slova a zvlastnos- ti aritmetiky plovouci carky a celociselneho deleni se ukazaly v praxi nevelkymi. Ostatni vlastnosti technickeho vybaveni se odrazeji v rozdilnych implementacich. Nektere z nich, zejmena rozsireni znamenka /pri konverzi zaporneho znaku do zaporneho cisla/ a poradi ve kterem jsou slabiky ukladany do slova, jsou drobnosti, ktere musi byt peclive studovany. Mhohe dalsi pro- blemy jiz nejsou zavazne. Pocet registrovych promennych, ktere mohou byt skutecne umisteny v registrech, je rozdilny na ruznych systemech, podob- ne jako soubor platnych typu. Je veci prekladace, aby osetril spravne takove situace. Prebyvajici nebo neplatne registrove deklarace jsou jednoduse ignorovany. Nektere problemy mohou vzniknout pri pouziti pochybnych pro- gramovych praktik. Je velice nerozumne psat takove programy, ktere zavisi na takovych vlastnostech. Poradi vyhodnoceni argumentu funkci neni v definici jazyka specifikovano. Na systemu PDP-11 je zprava a na ostatnich sys- temech zleva doprava. Poradi, ve kterem muze dojit k vedlejsim efektum, neni take specifikovano. Protoze znakove konstanty jsou ve skutecnosti objekty typu INT, jsou dovoleny i viceznakove konstanty. Skutecna implemen- tace je zavisla na technickych prostredcich, protoze poradi ve kterem jsou znaky prirazovany slovum se na ruznych systemech lisi. Bitova pole jsou prirazena slovum a znaky jsou prirazeny celym cislum zprava doleva na systemu PDP-11 a zleva doprava na ostatnich systemech. Tyto rozdily jsou neviditelne samotnym programum, pokud si nedopravaji rafinovanosti s typy dat /nap- riklad, kdyz uskutecni konverzi ukazovatka na objekt typu INT na ukazovatko na objekt typu CHAR, ktere potom pouzije k prohlizeni puvodniho objektu/, ale musi odpovidat vlastnostem technickeho vybaveni. Jazyk prijimany ruznymi prekladaci se lisi nepatrnymi detai- ly. Napriklad prekladac implementovany na systemu PDP-11 nemuze inicializovat struktury, ktere obsahuji bitova pole. .pa Š.po 12 17. Anachronismy ---------------- Protoze jazyk C je jazyk, ktery je ve vyvoji, mohou byt ve starsich programech nalezeny nektere neobvykle konstrukce. Ackoliv nektere prekladace dovoluji tyto anachronismy pouzi- vat, budou nakonec odstraneny a problem prenositelnosti bude prekonan. Drivejsi verze jazyka C pouzivaly formu =op namisto formy op= pro operatory prirazeni. Tim byla zpusobena dvojznacnost ve vyrazu: x=-1 Tento vyraz opravdu bude dekrementovat promennou x, protoze znaky "=" a "-" jsou v bezprostrednim sousedstvi, ale mohl by byt velmi snadno zamenen za prikaz prirazeni hodnoty -1 prome- nne x. Byla take zmenena syntaxe inicializace, drive nebyl pouzi- van pri inicializaci znak prirazeni "=". Tedy drivejsi zapis: INT x 1; je nyni nahrazen zapisem: INT x = 1;