.pl 60 .po 12 .mt 2 .mb 2 .pn 153 PRILOHA A: REFERENCNI POPIS C JAZYKA ------------------------------------ 1.Uvod ------ Tato priloha popisuje jazyk C, takovy jaky je na pocitacich DEC PDP-11, Honeywell 6000, IBM System/370 a Interdata 8/32. Tam kde mezi temito jazyky existuji rozdily, zameruje se popis na verzi pro system PDP-11, ale soucasne zduraznuje implemen- tacne-zavisle skutecnosti. Az na nekolik vyjimek jsou tyto roz- dily zpusobeny rozdilnym technickym vybavenim /hardware/ vyse uvedenych pocitacu. Jinak jsou vyse uvedene predkladace ja- zyka C vpodstate zcela kompatibilni. 2. Lexikalni konvece -------------------- Existuje sest kategorii lexikalnich polozek: identifikatory, klicova slova, konstanty, retezce, operatory a separatory. Me- zery, tabulatory, znaky nova radka a komentare /souhrne nazy- vane nevyznamne znaky/ jsou ignorovany pokud neslouzi k oddele- ni lexikalnich polozek. Nektere nevyznamne znaky jsou pozadova- ny pro oddeleni sousednich identifikatoru, klicovych slov a konstant. Jestlize byl vstupni retezec znaku rozdelen na lexikalni po- lozky az po nejaky dany znak, bude nasledujici lexikalni poloz- ka obshovat nejdelsi mozny retezec znaku, ktery by mohl tvorit nejakou lexikalni polozku. 2.1. Komentare -------------- Komentar je uveden dvojici znaku "/*" a ukoncen dvojici zna- ku "*/". Komentare nesmeji byt do sebe navzajem vnorene. 2.2. Identifiktory /jmena/ -------------------------- Identifikator je rada pismen a cislic. Prvni znak identifi- katoru musi byt vzdy pismeno. Znak "_" se radi k pismenum. Jsou rozlisovana mala a velka pismena. Pouze prvnich 8 znaku iden- tifikatoru je vyznamnych, ackoliv identifikator muze byt utvo- ren z vice znaku. Pro externi identifikatory, ktere jsou pouzi- vany ruznymi prekladaci jazyka symbolickych adres a zavadecimi programy, plati prisnejsi pravidla: DEC PDP-11 7 znaku, mala i velka pismena rozlisuje Honeywell 6000 6 znaku, nerozlisuje mala a velka IBM 360/370 7 znaku, nerozlisuje mala a velka Interdata 8/32 8 znaku, mala i velka rozlisuje 2.3 Klicova slova ------------------ Š Nasledujici identifikatory jsou rezervovany jako klicova slova a nesmeji byt pouzity v jinem vyznamu: int extern else char register for float typedef do double static while struct goto switch union return case long sizeof default short break entry unsigned continue auto if Klicove slovo entry neni doposud implemetovano na zadnem z vyse uvedenych kompilatoruu, ale je rezervovano pro budouci pouziti. Nektere dalsi implementace C jazyka obsahuji take rezervovana slova fortran a asm. 2.4 Konstanty -------------- Existuje nekolik typu konstant, ktere budou popsany dale. Jejich zavislosti na technickych prostredcich jsou shrnuty v odstavci 2.6. 2.4.1 Celociselne konstanty ---------------------------- Celociselna konstanta se sklada ze rady cislic. Jestlize ta- to rada zacina cislici 0 je konstanta predpokladana v oktalove soustave namisto dekadicke. Napr. cislice 8 a 9 maji v oktalo- ve soustave vyjadreni 10 a 11. Rada cislic, ktera je predchaze- na znaky "0x" nebo "0X" je chapana v soustave hexadecimalni. Hexadecimalni cislice obsahuji navic znaky "a" nebo "A" az "f" nebo "F", ktere odpovidaji cislum 10 az 15. Dekadicka konstanta jejiz hodnota je vetsi nez nejvetsi cele cislo se znamenkem, ktere muze dany typ pocitace zpracovat se chape jako konstanta typu long. Oktalova nebo hexadecimalni konstanta, jejiz hodno- ta je vetsi nez nejvetsi cele cislo bez znamenka, ktere muze dany typ pocitace zpracovat se take chape jako konstanta typu long. 2.4.2 Explicitni konstanty typu long ------------------------------------- Dekadicka, oktalova nebo hexadecimalni celociselna konstan- ta, ktera je bezprostredne nasledovana znakem "l" nebo "L" je chapana jako konstata typu long. Jak bude dale diskutovano, na nekterych pocitacich mohou byt konstanty typu cele cislo a typu long povazovany za totozne. 2.4.3 Znakove konstanty ------------------------ Š Znakova konstanta je znak uzavren mezi jednoduche uvozovky, napr. 'x'. Hodnota znakove konstanty je ciselena hodnota znaku v pouzitem znakovem systemu. Nektere nezobrazitelne znaky, jednoduche uvozovky "'" a zpetne lomitko "\" mohou byti pouzity jako znakove konstanty s vyuzitim nasledujici tabulky: nazev znaku: oznaceni: vkladany retezec znaku: ----------- -------- ----------------------- novy radek NL nebo LF \n tabulator HT \t zpetny vymaz BS \b navrat voziku CR \r nova stranka FF \f zpetne lomitko \ \\ jednoduche uvoz. ' \' retez bitu ddd \ddd Retezec "\ddd" se sklada ze znaku zpetne lomitko, ktere je nasledovano 1, 2 nebo 3 oktalovymi cislicemi, ktere specifiku- ji hodnotu pozadovaneho znaku. Specialnim pripadem pouziti teto konvence je retezec znaku "\0", ktery predstavuje znak NULL. Jestlize znak, ktery nasleduje za znakem zpetne lomitko neni zadny z vyse vyjmenovanych je znak zpetne lomitko ignorovan. 2.4.4 Konstanty v plovouci carce --------------------------------- Konstanta v plovouci carce se sklada z celociselne casti, desetinne tecky a desetinne casti, znaku "e" nebo "E" a pripad- ne celociselneho exponentu se znamenkem. Celociselna a desetin- na cast se skladaji z rady cislic. Bud celociselna nebo dese- tinna cast muze byt vynechana, ale nikoliv obe dve zaroven. Bud desetinna tecka nebo znak "e" /"E"/ a exponent muze byt vyne- chan, ale nikoliv oba soucasne. Kazda konstanta v plovouci car- ce je chapana s dvojnasobnou presnosti. 2.5 Retezce ------------ Retezec je rada znaku uzavrena mezi dvojite uvozovky, napr. "...". Retezec je objekt typu pole znaku a jeho ukladaci trida je static /viz. odstavec c.4/ a je inicializovan danymi znaky. Vsechny retezce, i identicke, jsou ruzne. Prekladac umisti na konec kazdeho retezece znak \0 proto, aby program mohl najit konec retezce. Uvnitr retezce musi byt znak dvojite uvozovky predchazen znakem zpetne lomitko. Dale mohou byt pouzity stejne prepinaci posloupnosti, ktere byly popsany v odstavci c.2.4.3. Znak zpetne lomitko, ktery je bezprostredne nasledovan zna- kem nova radka je spolu s nim ignorovan. 2.6 Technicke vybaveni ---------------------- Nasledujici tabulka shrnuje vlastnosti technickeho vybaveni jiz vyse zminenych ctyr typu pocitacu. Ackoliv tyto vlastnosti Šmaji vliv na prenositelnost programu, ve skutecnosti je daleko mene problemu, nez by bylo mozne ocekavat. DEC PDP-11 Honeywell 6000 IBM 370 Interdata 8/32 ASCII ASCII EBDIC ASCII char 8 bits 9 bits 8 bits 8 bits int 16 36 32 32 short 16 36 16 16 long 32 36 32 32 float 32 36 32 32 double 64 72 64 64 rozsah (+-10)** (+-10)** (+-10)**(+-10)** (+-38) (+-38) (+-76) (+-76) poznamky: vsechny systemy maji cisla s plovouci carkou, ktera maji 8-mi bitovy exponent. 3. Syntakticky zapis -------------------- V syntaktickem zapise, ktery je pouzit v teto priloze, jsou syntakticke kategorie oznacovany malymi pismeny. Lite- raly a znaky jsou oznaceny velkymi pismeny. Ruzne kategorie jsou vypsany na samostatnych radcich. Nepovinny terminalni nebo neterminalni symbol je oznacen znaky "???".. Napriklad: (expression???) oznacuje nepovinny vyraz uzavreny v zavorkach. Syntaxe je shrnuta v odstavce c. 18. 4. Co je to jmeno? ------------------ V C jazyku ma kazdy identifikator prideleny dva atributy: ukladaci tridu a typ. Ukladaci trida urcuje umisteni a dobu existence pameti pridelene identifikatoru. Typ urcuje vyznam hodnoty ulozene pameti pridelene identifikatoru. Existuji ctyri deklarovatelne ukladaci tridy: automatic, external, static a register. Promenne tridy automatic jsou lokalni pri kazdem vyvolani bloku /odstavec c.9.2/ a jsou zruseny po ukonceni bloku. Promenne tridy static jsou lokal- ni v bloku, ale uchovavaji svoji hodnotu az do opetovneho navratu do bloku.Externi promenne existuji a uchovavaji svoji hodnotu po celou dobu behu programu. Mohou byt pouzity pro komunikaci mezi ruznymi funkcemi, ktere mohou byt dokonce oddelene prekladany.Registrove promenne jsou ukladany do rych- lych registru pocitace /pokud jsou dovoleny/, jinak se chovaji stejne jako promenne tridy automatic. V jazyku C je definovano nekolik zakladnich typu objektu: Objekty deklarovane jako znakove /char/ jsou tak velike, aby do nich mohl byt ulozen libovolny clen pouziteho systemu znaku. Jestlize je nejaky znak ulozen do znakove promenne, jeho hodnota odpovida celociselnemu kodu tohoto znaku. Do promenne typu char mohou byt ulozeny libovolne hodnoty, ale Šjejich vyznam je zavisly na technickych prostredcich. Existuji tri ruzne promenne typu int, ktere jsou deklaro- vany jako short int, int a long int. Promenne typu long nebo int neposkytuji pro ulozeni promennych mene pameti nez promenne typu int nebo short. Implementace vsak muze byt takova, ze promenne typu short int nebo long int nebo obe dve mohou byt ekvivalentni zakladni promenne typu int. Zakladni promenna typu int ma velikost odpovidajici prirozene architekture po- citace. Ostatni typy promennych typu int jsou definovany pro specialni ucely. Cela cisla bez znamenka, deklarovana jako unsigned, pouzi- vaji aritmetiku modulo 2**n, kde n je pocet bitu v dane repre- zentaci celeho cisla. Na systemu PDP-11 nejsou promenne typu unsigned long int implementovany. Promenne typu floating point jednoduche i dvojnasobne pres- nosti mohou byt v nekterych implementacich totozne. Protoze vsechny predchazejici typy promennych mohou byt cha- pany jako cisla, mohou byt oznaceny take jako promenne typu aritmetic. Typy char a int vsech velikosti mohou byt souhrne oznacovany jako promenne typu integral. Promenne typu float a double mohou byt souhrne oznacovany jako promenne typu floa- ting. Mimo zakladni aritmeticke typy existuje v podstate nekonecny pocet odvozenych typu, ktere mohou byt od zakladnich odvozeny nasledujicimi zpusoby: pole /array/ objektu z ruznych typu funkce, ktere vraci objekty danych typu ukazovatka /pointers/ na objekty danych typu struktury obsahujici seznam objektu ruznych typu uniony /unions/ obsahujici soucasne nekolik objektu ruznych typu Vsechny tyto zpusoby mohou byt pouzity rekurzivne. 5. Objekty a l-hodnoty --------------------------- Pojem objekt znamena urcitou cast pameti, ktera slouzi k ulozeni nejake hodnoty a se kterou je mozne manipulovat. l-hodnota je vyraz, ktery ukazuje na nejaky objekt. Nejcastejsim prikladem takoveho vyrazu je identifikator. Existuji operatory, ktere poskytuji l-hodnoty, napr: jestlize E je vyraz typu ukazovatko, potom E je vyraz l- hodnoty ukazujici na objekt na ktery ukazuje E. Nazev "l- hodnota" je odvozen z prikazu prirazeni napr: E1 = E2, ve kterem levy operand E1 musi byt vyraz l-hodnoty. Diskuse vsech operatoru, ktera nasleduje, poskytne informace o tom, ktery operator ocekava operandy typu l-hodnota a ktery l-hodnoty poskytuje. L-hodnota je tedy vyraz, ktery muze byt na leve strane prirazeni. 6. Konverze ----------- Š Vetsina operatoru muze v zavislosti na jejich operandech zpusobit konverzi hodnoty operandu daneho typu na jiny typ. V teto casti prirucky bude objasneno, jake mohou byt vysled- ky takovych konverzi. Odstavec 6.6 souhrne vysvetli pravid- la, jaka jsou pozadovana jednotlivymi operatory. Dalsi infor- mace jsou dale podany u vysvetleni jednotlivych operatoru. 6.1 Znaky a cela cisla ---------------------- Znakove objekty a objekty typu short integer mohou byt pou- zity vsude tam, kde je dovoleno pouzit objekty typu integer. Ve vsech pripadech se vsak provadi konverze na typ integer. Pri konverzi objektu typu short integer na objekt typu integer se vzdy provadi znamenkove rozsireni, protoze objekty vsech typu integer jsou hodnoty se znamenkem. U objektu znakovych se zna- menkove rozsireni provadi v zavislosti na technickem vybaveni pocitace. Vzdy je vsak zaruceno, ze znak ze standartniho sou- boru znaku nema zapornou hodnotu. Z vyse uvedenych typu poci- tacu pouze system PDP-11 provadi znamenkove rozsireni u objek- tu typu char. Na tomto pocitaci je rozsah hodnot typu char od -128 do 127, pricemz znaky souboru ASCII maji vzdy kladne hodnoty. Znakova konstanta zadana pomoci zpetneho lomitka a oktalovych cislic muze znamenkovemu rozsireni podlehat a stat se tak negativni, napr. '\377' ma hodnotu -1. Kdykoliv je delsi objekt typu integer konvertovan na objekt typu short integer nebo char je zkracen z leva, bity navic jsou jednoduse ignorovany. 6.2 Plovouci carka a dvojnasobna presnost ----------------------------------------- Veskera aritmetika v plovouci carce je v C jazyku provadena v dvojnasobne presnosti. Kdykoliv se objekt typu plovouci car- ka vyskytne ve vyrazu je konvertovan na objekt typu dvojnasob- na presnost doplnenim nulami. Kdykoliv musi byt objekt dvojna- sobne presnosti konvertovan na objekt typu plovouci carka, napriklad pri pouziti prikazu prirazeni je objekt typu dvojna- sobne presnosti zaokrouhlen predtim nezli je zkracen na objekt typu plovouci carka. 6.3 Typy plovouci carky a typy celociselne ------------------------------------------ Konverze typu plovouci carky na typy celociselne jsou zavis- le na pouzitem technickem vybaveni, predevsim zkraceni zapor- nych cisel je na ruznych pocitacich odlisne. Vysledek je nede- finovany, jestlize konvertovana hodnota neni v rozsahu celych cisel. Konverze objektu celociselnych na objekty v plovouci carce jsou bez problemu. Muze dojit ke ztrate presnosti, jestlize .pa Š.po 12 objekt v plovouci carce nema dostatecny pocet bitu. 6.4 Ukazovatka a cela cisla --------------------------- Objekty typu integer nebo long integer mohou byt scitany a odcitany od objektu typu ukazovatko. V techto pripadech je prvni operand konvertovan tak, jak je popsano v casti popisu- jici operator scitani. Mohou byt take odectena dve ukazovatka, ktera ukazuji na objekty tehoz typu. Potom je vysledek konvertovan na celoci- selny typ, tak jak je popsano v casti popisujici operator rozdilu. 6.5 Cisla bez znamenka ---------------------- Pri jakekoliv kombinaci celeho cisla beze znamenka a nor- malniho celeho cisla je normalni cislo konvertovano na cislo beze znamenka a vysledek je beze znamenka. Jeho hodnota je nejmensi cele cislo beze znamenka, jehoz hodnota je kongruentni s cislem typu signed /modulo 2 ** sirka_slova/. Pri pouziti dvojkoveho doplnku pro cisla typu signed je konverze trivialni a ve skutecnosti nedojde ke zmene bitu v danem cisle. Pri konverzi objektu typu unsigned na objekt typu long, bude hodnota vysledku numericky rovna hodnote objektu typu unsigned. Pri konverzi se pouze doplni potrebny pocet nul z leva do cisla typu long. 6.6 Aritmeticke konverze ------------------------ Velky pocet operatoru zpusobuje konverze a vytvari vysledny typ podobnym zpusobem. Nasleduji tzv. obvykle aritmeticke kon- verze. - operandy typu char a short jsou konvertovany na typ int, ope- randy typu float jsou konvertovany na typ double. - jestlize jeden z operandu je typ double, jsou na tento typ konvertovany i zbyvajici operandy a take typ vysledku je double. - jinak, jestlize je jeden z operandu typu long, jsou na tento typ konvertovany i zbyvajici operandy a take typ vysledku long. - jinak, jestlize je jeden z operandu typu unsigned, jsou na tento typ konvertovany i zbyvajici operandy a take typ vy- sledku je unsigned. - jinak musi byt operandy typu int a to je take typ vysledku. .pa Š.po 3 7. Vyrazy --------- Priorita operatoru ve vyrazech je ta sama jako je poradi odstavcu v teto casti prirucky /tj. c.7/. Odstavec, ktery pred- chazi jine, popisuje operatory, ktere maji vyssi prioritu. Napriklad odstavec 7.4 popisuje operatory, ktere maji vyssi prioritu nezli operatory, ktere jsou popisovany v odstavcich 7.5 a dalsich. Operatory uvnitr kazdeho odstavce maji totoznou prioritu. Asociativita operatoru zleva ci zprava je uvedena pro kazdou skupinu operatoru zvlast. Priorita a asociativita vsech operatoru je shrnuta v odstavci c. 18. Mimo pravidla vyse uvedena je poradi vyhodnoceni vyrazu nedefinovano. Prekladac sam rozhodne o takovem vyhodnoceni castecnych vyrazu, ktere povazuje za efektivni, bez ohledu na vedlejsi efekt takovehoto vyhodnoceni. Poradi ve kterem dojde k vedlejsim efektum neni specifikovano. Vyrazy, ktere obsahuji komutativni a asociativni operatory (*,+,&,|,`) mohou byt prekladacem preskupeny, dokonce i kdyz obsahuji zavorky. Pri snaze dodrzet zadane poradi vyhodnoceni vyrazu musely by byt pouzity prechodne promenne. Osetreni situaci aritmetickeho preteceni a deleni nulou pri vyhodnoceni vyrazu je zavisle na technickem vybaveni. Vsechny existujici implementace jazyka C ignoruji celocisel- ne preteceni. Osetreni deleni nulou a vsech vyjimecnych situa- ci pri zpracovani cisel v plovouci carce je na ruznych poci- tacich odlisne a je obvykle umisteno v knihovne aritmetickych funkci jazyka C. 7.1 Zakladni vyrazy ------------------- Zakladni vyrazy vcetne . , - >, indexovych vyrazu a funk- cnoch volani jsou nasledujici: zakladni_vyraz: identifikator konstanta retezec (vyraz) zakladni_vyraz[vyraz] zakladni_vyraz(seznam_vyrazu???) zakladni_lhodnota.identifikator zakladni_vyraz->identifikator seznam_vyrazu: vyraz seznam_vyrazu, vyraz Identifikator je zakladnim vyrazem, jestlize je deklarovan vhodnym zpusobem, tak jak bude popsano dale. Typ identifikatoru je dan jeho deklaraci. Jestlize typ identifikatoru je "array of...", hodnota identifikatoru ve vyrazu je hodnotou ukazovat- ka na prvni objekt pole a typ vyrazu je "pointer to...". Navic identifikator pole neni vyraz typu lhodnoty. Podobne identifi- kator deklarovany jako "function returnig..." pouzity mimo funkcni volani je chapan jako "pointer to function retur- Š.po 12 ning ...". Konstanta je zakladni vyraz. Jeji typ muze byt int, long nebo double. Znakova konstanta ma typ int a konstanta v plovouci carce ma typ double. Retezec je zakladnim vyrazem. Jeho typ je vpodstate "array of char ...", ale plati pro nej ta sama pravidla, jaka byla jiz popsana pro identifikatory. Tj. typ je modifikovan na "pointer to char" a vysledkem je ukazovatko na prvni znak retezce. Existuje vyjimka z techto pravidel, ktera se uplatnuje pri inicializaci retezce, viz. odstavec 8.6. Ozavorkovany vyraz je zakladnim vyrazem jehoz typ je iden- ticky s typem neozavorkovaneho vyrazu. Pritomnost zavorek ne- ma vliv na to, je-li vyraz hodnotou nebo neni. Zakladni vyraz nasledovany vyrazem v hranatych zavorkach je zakladnim vyrazem. Intuitni pojeti takoveho vyrazu je, ze se jedna o indexovy vyraz. Zakladni vyraz ma typ "pointer to ...", indexovy vyraz ma typ int a typ vysledku je "...". Vyraz E1 [E2] je identicky /svoji definici/ s vyrazem *((E1) + (E2)). Dalsi informace potrebne pro pochopeni vyse uvedene notace jsou uvedeny v odstavcich 7.1, 7.2 a 7.4. Celkove shrnuti je dale obsazeno v odstavci 14.3. Funkcni volani nasledovane seznamem vyrazu, ktere jsou uzavreny v zavorkach, je zakladnim vyrazem. Seznam vyrazu muze byt prazdny. Zakladni vyraz je typu "function returning ..." a vysledek vraceny funkcnim volanim je typu "...". Identifi- kator, ktery je bezprostredne nasledovan levou zavorkou je kontexove chapan jako funkce, ktera vraci hodnotu typu int a nemusi byt proto deklarovan. Vsechny skutecne argumenty typu float jsou konvertovany pred vyvolanim funkce na typ double. Argumenty typu char a short jsou obdobne konvertovany na typ int a nazvy poli jsou konvertovany na typ pointer. Zadne dalsi konverze se automa- ticky neuskutecnuji, prekladac nekontroluje, zdali typy sku- tecnych argumentu odpovidaji typum argumentu formalnich. Jestlize je takova konverze potrebna je nutne pouzit explicitni konverzi, viz. odstavce 7.2 a 8.7. Pri priprave funkcniho volani se vytvori kopie kazdeho skutecneho argumentu, jedna se tedy o prenos argumentu jejich hodnotou. Funkce smi zmenit hodnoty vsech svych formalnich argumentu aniz dojde ke zmene hodnot skutecnych argumentu. Na druhe strane je mozne prenaset ukazovatka na dane objekty, ktere pak mohou byt funkci meneny. Nazev pole je chapan jako ukazovatko. Poradi vyhodnoceni argumentu neni jazykem defino- vano, zavisi od pouziteho prekladace. Jsou dovolena rekur- zivni volani libovolne funkce. Zakladni vyraz bezprostredne nasledovany teckou a identifi- katorem je zakladnim vyrazem. Prvni vyraz musi byt lhodnotou urcujici strukturu nebo union. Identifikator musi byt nazev polozky struktury nebo unionu. Zakladni vyraz nasledovany sipkou /je vytvorena ze znaku "-" a ">"/ a identifikatorem je vyrazem. Prvni vyraz musi byt lhodnotou urcujici strukturu nebo union. Identifikator musi byt nazev polozky struktury nebo unionu. Vysledkem je lhodnota urcujici danou polozku struktury nebo unionu, na kterou ukazuje vyraz typu ukazovatko. Š.po 3 Vyse uvedena pravidla znamenaji ze vyrazy E1->MOS a (*E1).MOS jsou totozne. Struktury a uniony jsou objasneny v odstavci c.8.5. 7.2 Unarni operatory --------------------- Vyrazy s unarnimi operatory jsou vyhodnocovany zprava doleva. unarni vyraz: *vyraz &lhodnota -vyraz !vyraz ^vyraz ++lhodnota --lhodnota lhodnota++ lhodnota-- (nazev_typu) vyraz SIZEOF vyraz SIZEOF (nazev_typu) Unarni operator "*" znamena tzv. neprimy pristup. Vyraz musi byt ukazovatko a vysledkem je lhodnota urcujici objekt, na ktery vyraz ukazuje. Jestlize typ vyrazu je "pointer to ...", potom typ vysledku je "...". Vysledkem unarniho operatoru "&" je ukazovatko na objekt ur- ceny lhodnotou. Jestlize typ lhodnoty je "...", potom typ vys- ledku je "pointer to ...". Vysledek unarniho operatoru "-" je negace jeho operandu. Jsou uskutecneny obvykle aritmeticke konverze. Negace hodnoty bez znamenkoveho typu je vypoctena tak, ze hodnota vyraz je odectena od hodnoty 2**n, kde n je pocet bitu cisla typu int. Neexistuje unarni operator +. Vysledkem operatoru logicke negace "!" je hodnota 1, jestli- ze hodnota operandu je 0 a hodnota 0, jestlize hodnota operandu je ruzna od hodnoty 0. Typ vysledku je int. Muze byt pouzit ve vyrazech s libovolnym aritmetickym typem nebo ve vyrazech s ukazovatky. Operator "^" vytvari jednotkovy komplement sveho operandu. Pri jeho pouziti se uskutecni obvykle aritmeticke konverze. Operand musi byt typu int. Operator "++", ktery predchazi svuj operand zpusobi jeho inkrementaci. Tato hodnota se stane novou hodnotu objektu, ktery je urcen lhodnotou, ale samotna tato hodnota neni lhodno- tou. Vyraz ++x je rovnoceny vyrazu x += 1. Dalsi informace jsou v odstavcich 7.4 /scitani/ a 7.14 /operatory prirazeni/. V techto odstavcich jsou take informace o konverzich,ktere se pri pouziti tohoto operatoru uskutecni. Operator "--", ktery predchazi svuj operand, zpusobi jeho dekrementaci. Ostatni vlastnosti jsou analogicke vlastnostem predchazejiciho operatoru. Pri pouziti operatoru "++", ktery nasleduje svuj operand se stane vysledkem hodnota objektu, ktera je urcena lhodnotou a teprve potom dojde k inkrementaci objektu. Typ vysledku je Š.po 12 tentyz jako je typ lhodnoty. Operator "--", ktery nasleduje svuj operand ma vlastnosti analogicke vlastnostem predchazejiciho operatoru. Jmeno typu, ktere je uzavreno mezi zavorky a je nasledovano vyrazem, zpusobi ze hodnota vyrazu bude konvertovana na odpo- vidajici hodnotu daneho typu. Konstrukce tohoto typu se nazyva "cast". Jmena typu jsou vysvetlena v odstavci 8.7. Operator SIZEOF poskytuje hodnotu, ktera udava velikost operandu /ve slabikach/. Termin slabika /byte/ neni jazykem definovan vyjma vztahu k hodnote, ktera je poskytovana opera- torem SIZEOF. Nicmene, ve vsech existujicich implementacich jazyka C je byte chapan jako rozmer objektu char. Pokud je ten- to operator pouzit na objekt typu pole, je vracena hodnota uda- vajici celkovy pocet slabik pole. Velikost operandu je urcena prostrednictvim deklaraci jednotlivych objektu ve vyrazu. Tento vyraz je semanticky celociselnou konstantou a muze byt pouzit vsude tam, kde je dovoleno pouzit konstanty. Hlavni pouziti tohoto operatoru je v komunikacich s podprogramy jako jsou alokacni podprogramy a podprogramy systemoveho vstupu a vystu- pu. Operator SIZEOF muze byt take pouzit se jmenem typu, ktere je uzavreno v zavorkach. V tomto pripade poskytne velikost daneho typu ve slabikach. Konstrukce SIZEOF (type) je chapana jako celek. Vyraz SIZEOF (type)-2 je totozny s vyrazem (SIZEOF(type))-2. 7.3 Multiplikativni operatory ------------------------------ Multiplikativni operatory jsou *, / a %. Jsou vyhodnocovany zleva doprava a taky se pri jejich zpracovani uskutecni obvyk- le aritmeticke konverze. Multiplikativni_vyraz: vyraz * vyraz vyraz / vyraz vyraz % vyraz Binarni operator "*" oznacuje soucin. Tento operator je asociativni a vyraz, obsahuje nekolik soucinu na te same urovni muze byt prekladacem preskupen. Binarni operator "/" oznacuje deleni. Pri deleni kladnych cisel je vysledek zaokrouhlen smerem k nule, pri deleni zapor- nych cisel je zpusob zaokrouhleni zavisly na technickem vyba- veni pocitace. Na vsech jiz vyse uvedenych pocitacich ma zbytek po deleni vzdy stejne znamenko jako delenec. Tzn. ze plati nasledujici vztah: (a/b)*b + a%b = a /pokud je b ruzne od 0/. Binarni operator "%" poskytuje zbytek po deleni prvniho ope- randu druhym. Uskutecni se obvykle aritmeticke konverze. Ope- randy nesmeji byt typu float. .pa Š.po 3 7.4 Aditivni operatory ----------------------- Aditivni operatory jsou + a -. Jsou vyhodnocovany zleva dop- rava a take se pri jejich zpracovani uskutecni obvykle aritme- ticke konverze. V nekterych pripadech mohou byt operandy ruz- nych typu. Aditivni_vyraz: vyraz + vyraz vyraz - vyraz Operator "+" poskytuje sumu svych operandu. Muze byt vytvo- ren soucet ukazovatka ukazujiciho na dany objekt a hodnoty celociselneho typu. Druhy operand je ve vsech pripadech kon- vertovan na posunuti ve slabikach, ktere je ziskano soucinem druheho operandu s velikosti objektu, na ktery ukazuje ukazo- vatko. Vysledkem je ukazovatko na objekt tehoz typu. Tedy jestlize P je ukazovatko na objekt v poli, potom P+1 je ukazo- vatko na nasledujici objekt pole. Zadne dalsi kombinace typu operandu jiz nejsou dovoleny. Operator "+" je asociativni a vyraz, ktery obsahuje neko- lik souctu na teze same urovni muze byt prekladacem preskupen. Operator "-" poskytuje rozdil operandu. Pri jeho vyhodno- ceni se uskutecni obvykle aritmeticke konverze. Hodnota libo- volneho celociselneho typu muze byt odectena od ukazovatka, potom se uskutecni analogicke konverze, ktere se uskutecni pri pouziti operatoru "+". Jestlize se uskutecni rozdil dvou ukazovatek, ktere ukazuji na objekty stejneho typu, potom je vysledek konvertovan, dele- nim velikosti objektu, na hodnotu typu int, ktera predstavuje pocet objektu, ktere oddeluji objekty, na ktere ukazuji ukazo- vatka. Tato konverze bude davat necekane vysledky pokud ukazo- vatka nebudou ukazovat do tehoz pole, protoze potom, i v situaci, kdy pole budou obsahovat objekty tehoz typu, neni zaruceno, ze rozdil ukazovatek bude celistvym nasobkem delky objektu. 7.5 Operatory posuvu --------------------- Operatory posuvu << a >> se vyhodnocuji zleva doprava. Pri jejich vyhodnoceni se uskutecni obvykle aritmeticke konverze. Oba operandy musi byt celociselnych typu. Pravy operand je vzdy konvertovan na typ int. Typ vysledku je vzdy roven typu leveho operandu. Vysledek neni definovan, jestlize pravy ope- rand je negativni, nebo je vetsi anebo roven velikosti leveho operandu v bitech. vyraz_posuvu: vyraz << vyraz vyraz >> vyraz Hodnota vyrazu E1<>E2 je rovna hodnote E1 posunute o E2 bitu Š.po 12 vpravo. Posuv vpravo je logickym posuvem /uvolnene bitove po- zice jsou doplnovany 0/, jestlize je operand na leve strane typu unsigned. Pokud neni typu unsigned muze se jednat /napr. na systemu PDP-11/ o posuv aritmeticky /uvolnene bity se zapl- nuji kopii znamenkoveho bitu/. 7.6 Relacni operatory ---------------------- Relacni operatory jsou vyhodnocovany zleva doprava, ale tato skutecnost neni priliz uzitecna. Vyraz a vyraz vyraz <= vyraz vyraz >= vyraz Operatory < /mensi nez/, > /vetsi nez/, <= /mensi nebo rovno/ a >= /vetsi nebo rovno/ poskytuji hodnotu 0, jestlize je dany vyraz nepravdivy a hodnotu 1, jestlize je dany vyraz pravdivy. Typ vysledku je int. Pri vyhodnoceni se uskutecni obvykle aritmeticke konverze. Mohou byt porovnavany take dve ukazovat- ka, vysledek je potom zavisly na umisteni danych objektu, na ktere obe ukazovatka ukazuji, v adresnim prostoru pocitace. Porovnavani ukazovatek je prenositelne pouze v tom pripade, kdy se jedna o ukazovatka ukazujici do tehoz pole. 7.7 Operatory porovnani ------------------------ vyraz_porovnani: vyraz == vyraz vyraz != vyraz Operatory == /rovno/ a != /nerovno/ jsou analogicke operatorum relacnim, vyjma jejich nizsi priority. Tedy vyraz ad je roven hodnote 1, kdykoliv vyrazy ad poskytuji tutez pravdivostni hodnotu. Objekt typu ukazovatko muze byt porovnavan s hodnotou typu int, ale vysledek je zavisly na technickych prostredcich vypo- cetniho systemu, pokud se nejedna o porovnani s konstantou typu int rovnou 0. Ukazovatko, ktere ma hodnotu 0 neukazuje na zadny objekt. V beznem pouziti se predpoklada, ze takove ukazovatko ma hodnotu NULL. 7.8 Bitovy operator AND ------------------------ AND_vyraz: vyraz & vyraz Operator "&" je asociativni a vyraz obsahujici vice techto ope- ratoru muze byt preskupen. Uskutecni se obvykle aritmeticke konverze. Vysledek je provedeni funkce AND na vsech bitech ope- Š.po 3 randu. Operator muze byt pouzit pouze s operandy typu int. 7.9 Bitovy operator XOR ------------------------ XOR_vyraz: vyraz ^ vyraz Operator "^" je asociativni a vyraz obsahujici vice techto ope- ratoru muze byt preskupen. Uskutecni se obvykle aritmeticke konverze. Vysledek je provedeni funkce XOR na vsech bitech ope- randu. Operator muze byt pouzit pouze s operandy typu int. 7.10 Bitovy operator OR ------------------------ OR_vyraz: vyraz | vyraz Operator "|" je asociativni a vyraz obsahujici vice techto ope- ratoru muze byt preskupen. Uskutecni se obvykle aritmeticke konverze. Vysledek je provedeni funkce OR na vsech bitech ope- randu. Operator muze byt pouzit pouze s operandy typu int. 7.11 Logicky operator AND -------------------------- logicky_and_vyraz: vyraz && vyraz Operator "&&" je vyhodnocovan zleva doprava. Vrati hodnotu 1, jestlize jsou oba operandy ruzne od 0, jinak vrati hodnotu 0. Na rozdil od operatoru "&" zarucuje operator "&&" vyhodnoceni vyrazu zleva doprava. Navic druhy operand neni vubec vyhodnoco- van, jestlize jiz byla vyhodnocena hodnota prvniho operandu rovna 0. Operandy nemusi byt tehoz typu, ale musi se jednat o typy zakladni nebo ukazovatka. Vysledek je vzdy typu int. 7.12 Logicky operator OR ------------------------- logicky_or_vyraz: vyraz || vyraz Operator "||" je vyhodnocovan zleva doprava. Vrati hodnotu 1, jestlize aspon jeden z jeho operandu je ruzny od hodnoty 0, jinak vrati hodnotu 0. Na rozdil od operatoru "|" zarucuje operator "||" vyhodnoceni vyrazu zleva doprava. Navic druhy operand neni vubec vyhodnocovan, jestlize jiz byla vyhodnocena hodnota prvniho operandu ruzna od 0. Operandy nemusi byt tehoz typu, ale musi se jednat o zakladni typy nebo ukazovatka. Vysledek je vzdy typu int. .pa Š.po 12 7.13 Operator podminky ----------------------- vyraz_podminky: vyraz ? vyraz : vyraz Vyrazy s podminkou jsou vyhodnocovany zprava doleva. Nejprve je vyhodnocen prvni vyraz, a jestlize je ruzny od 0 je vysled- kem hodnota druheho vyrazu, jinak je vysledkem hodnota tretiho vyrazu. Jestlize je to mozne, uskutecni se obvyk- le aritmeticke konverze tak, aby druhy a treti vyraz mely tentyz typ. Jestlize se jedna o ukazovatka na objekty tehoz typu, vysledek ma tentyz typ. Pokud je jeden vyraz ukazovat- ko a druhy konstanta rovna 0, ma vysledek typ ukazovatka. Vyhodnuceje se vzdy pouze jeden z vyrazu za znakem "?". 7.14 Operatory prirazeni ------------------------- Je velky pocet operatoru prirazeni, ktere jsou vyhodnoco- vany zprava doleva. Vsechny vyzaduji na sve leve strane lhod- notu a vysledny typ prirazeni je dan take operandem na leve strane. Hodnota operatoru prirazeni je hodnota, ktera je ulozena do operandu na leve strane. Obe dve casti slozeneho operatoru prirazeni jsou samostatne syntakticke jednotky. vyraz prirazeni: lhodnota = vyraz lhodnota += vyraz lhodnota -= vyraz lhodnota *= vyraz lhodnota /= vyraz lhodnota %= vyraz lhodnota >>= vyraz lhodnota <<= vyraz lhodnota &= vyraz lhodnota ^= vyraz lhodnota != vyraz Pri jednoduchem prirazeni /=/ je hodnota vyrazu umistena do objektu, ktery je urcen lhodnotou. Jestlize oba operandy maji aritmeticky typ, je pravy operand pred uskutecnenim prirazeni konvertovan na typ leveho operandu. Vyraz prirazeni ve forme E1 op = E2 je analogicky vyrazu E1 = E1 op(E2), vyjma toho faktu, ze vyraz E1 je vyhodnocovan pouze jednou. U slozenych vyrazu += a -= muze byt levy operand ukazovatkem. Potom je pravy /celociselny/ operand konvertovan tak, jak je vysvetleno v odstavci 7.4. Vsechny prave operandy a vsechny leve operandy, ktere nejsou ukazovatky musi mit ari- tmeticke typy. Prekladac skutecne umoznuje, aby hodnota ukazovatka mohla byt prirazena promenne typu int, aby hodnota typu int mohla byt prirazena k ukazovatku, a hodnota ukazovatka ukazovatku jineho typu. Operace prirazeni je pouhym prekopirovanim hod- not bez konverzi. Takoveto pouziti neni prenositelne, a mohou vzniknout ukazovatka, ktera nemaji smysl. Nicmene pri prirazeni Š.po 3 konstanty 0 ukazovatku je zaruceno, ze ukazovatko nebude ukazo- vat na zadny objekt. 7.15 Operator carky -------------------- vyraz_s_carkou: vyraz , vyraz Dvojice vyrazu oddelenych carkou je vyhodnocena zleva doprava a hodnota leveho vyrazu je zapomenuta. Typ a hodnota vysledku je stejna jako typ a hodnota praveho operandu. V takovem kontextu, kde carka muze mit nejaky specialni vyznam, napriklad v seznam skutecnych argumentu funkce /odstavec 7.1/ nebo seznamu pri inicializaci /odstavec 8.6/, muze se operator "," ve_vyznamu, ktery je popisovan v tomto odstavci vyskytovat pouze mezi zavorkami. Napriklad: f(a, (t=3, t+2), c) Tato funkce ma tri argumenty, druhy z nich ma hodnotu 5. 8. Deklarace ------------ Deklarace jsou uzivany pro specifikaci jednotlivych identi- fikatoru C jazyka. Nemusi vzdy uskutecnit soucasne rezervaci mista pameti pro dany identifikator. Deklarace maji nasledujici formu: deklarace: specifikator_deklarace seznam_deklarace???; Seznam_deklarace obsahuje nazvy identifikatoru, ktere maji byt deklarovany. Specifikator_deklarace se sklada ze specifikace typu a tri- dy ulozeni. specifikator_deklarace: specifikace_typu specifikator_deklarace??? specifikace_ulozeni specifikator_deklarace??? Seznam deklaraci musi byt usporadan danym zpusobem, ktery bude dale vysvetlen. 8.1 Specifikace tridy ulozeni ------------------------------ specifikace_ulozeni: AUTO STATIC EXTERN REGISTER TYPEDEF Specifikace TYPEDEF nerezervuje zadnou pamet pro ulozeni Š.po 12 objektu a je zarazena mezi specifikace ulozeni pouze z duvodu syntakticke konvence. Tato specifikace je vysvetlena v odstav- ci c. 8.8. Vyznam zbyvajicich specifikaci byl objasnen v odstavci c. 4. Specifikace AUTO, STATIC a REGISTER jsou soucasne i defini- cemi a zpusobuji rezervovani prislusneho mnozstvi pameti. V pripade specifikace EXTERN se jedna o externi definici /viz. odstavec c.10./ identifikatoru definovaneho mimo funkci ve ktere je deklarovan. Deklarace REGISTER je nejlepsi zpusob deklarace objektu, pro ktery by mohla byt pouzita deklarace AUTO. Tato deklara- ce naznaci prekladaci, ze se jedna o promennou, ktera bude velmi casto pouzivana. Pouze nekolik prvnich takovych dekla- raci vsak bude efektivnich. Navic, pouze nektere typu promen- nych mohou byt ulozeny v registrech. Na systemu PDP-11 se jedna o typy int, char a ukazovatko. Dalsi vyjimka, ktera plati pro registrovane promenne je ta, ze na ne nelze pouzit adresovy operator "%". Pri pouziti registrovych promennych je mozne ocekavat mensi a rychlejsi programy, ale budouci zlepseni generace strojoveho kodu prekladacem je mohou ucinit zbytecnymi. Nejvyse jedna specifikace_ulozeni muze byt v jedine deklara- ci. Jestlize specifikace_ulozeni chybi, predpoklada se specifi- kace AUTO uvnitr funkci a extern mimo ne. Vyjimkou jsou dekla- race funkci, ktere nikdy nejsou AUTO. 8.2 Specifikace typu --------------------- Specifikace_typu: CHAR SHORT INT LONG UNSIGNED FLOAT DOUBLE specifikator_structury specifikator_unionu typedef_jmeno Nazvy LONG, SHORT a UNSIGNED mohou byt pouzita jako adjektiva. Jsou dovoleny nasledujici kombinace: SHORT INT LONG INT UNSIGNED INT LONG FLOAT Vyznam posledni kombinace je tentyz jako specifikace DOUBLE. Jinak smi byt v deklaraci pouzit pouze jedna specifikace typu. Jestlize specifikace typu v deklaraci chybi, predpoklada se specifikace INT. Specifikace struktur a unionu jsou vysvetleny v odstavci c. 8.5, deklarace s konstrukci typedef_jmeno jsou objasneny v odstavci c. 8.8. Š.po 3 8.3 Deklaratory ---------------- Seznam deklaratoru je seznam polozek oddelenych carkami, z nichz kazda muze obsahovat inicializacni cast. seznam_deklaratoru: init_dekladator init_deklarator seznam_deklaratoru init_deklarator: deklarator iniciator??? Inicializatory jsou vysvetleny v odstavci c. 8.6. Specifikace v deklaraci urcuji typ a tridu ulozeni objektu, ktere jsou urceny deklaratory. Syntaxe deklaratoru je nasledujici: deklarator: identifikator (deklarator) *deklarator deklarator() deklarator [konstantni vyraz???] 8.4 Vyznam deklaratoru ----------------------- Kazdy deklarator je v podstate tvrzenim o vlastnostech nejakeho objektu. Pokud se takovy deklarator te same formy vyskytne ve vyrazu, urcuje objekt daneho typu a tridy ulozeni. Kazdy deklarator obsahuje pouze jediny identifikator, a to ten, ktery je prave deklarovan. Pokud ma deklarator tvar pouheho identifikatoru, ziska tento identifikator vlastnosti urcene specifikacni casti deklarace. Deklarator uzavreny mezi zavorkami je identicky s deklara- torem, ktery mezi zavorkami uzavren neni. Moznost zavorek je zde proto, aby bylo mozne vytvaret slozene deklaratory, je- jichz vyznam je urcen umistenim zavorek. Predpokladejme nasledujici deklaraci: T D1 Kde T je specifikator typu /napriklad INT atd./ a D1 je dekla- rator. Predpokladejme, ze tato deklarace vytvori identifikator majici typ "...T", kde "..." je prazdny retezec pokud se jedna o zakladni identifikator. Tedy typ identifikatoru x je INT, pokud byl deklarovan deklaraci: "INT x". Pokud ma deklarator D1 tvar: *D typ identifikatoru je:"... pointer to T". Jestlize ma deklara- tor D1 tvar: Š.po 12 D() Typ identifikatoru je "... function returning T". Jestlize ma deklarator D1 tvar: D [konstantni_vyraz] nebo D[] typ identifikatoru je "... array of T". V prvnim pripade je konstantni vyraz vyhodnocen v dobe prekladu a jeho typ je int. Konstantni vyrazy jsou definovany v odstavci c. 15. Pokud je nekolik specifikaci "array of" vedle sebe, je vytvoreno vice- rozmerne pole. Konstantni vyraz, ktery urcuje velikost pole je nepovinny pouze u prvniho clenu vicenasobne specfikace "array of". Tato moznost je vyhodna,pokud se jedna o externi pole a jeho skutecna definice je v jine casti programu. Prvni konstantni vyraz muze chybet take v pripade, kdy je deklarator nasledovan inicializatorem. V takovem pripade je velikost pole urcena z poctu polozek inicalizatoru. Pole smi byt utvoreno z jednoho ze zakladnich typu, z ukazo- vatek, ze struktur nebo unionu, anebo z jineho pole /potom se jedna o pole vicerozmerne/. Ve skutecnosti vsak nejsou dovoleny vsechny moznosti vytvo- reni deklaratoru, ktere povoluje vyse uvedena syntaxe. Omezeni jsou nasledujici: - funkce nesmeji vracet objekty typu pole, struktury, unionu nebo funkce, ackoliv mohou vracet ukazovatka na vyse uvedene objekty - neexistuji pole funkci, ale mohou existovat pole ukazova- tek na funkce - struktury a uniony nesmeji obsahovat funkce, ale mohou obsa- hovat ukazovatka na funkce. Napriklad deklarace: INT i, *ip, f(), *fip(), (*pfi)(); deklarujici celociselnou promennou i, ukazovatko ip na promen- nou typu int, funkci f, ktera vraci promennou typu int, funkci fip, ktera vraci ukazovatko na promennou typu int a ukazovatko pfi na funkci, ktera vraci promennou typu int. Je velmi uzi- tecne srovnat posledni dve deklarace. Deklaraci *fip() je moz- ne take napsat ve tvaru *(fip()), ze ktereho je videt, ze po- dobne jako pri vyhodnoceni vyrazu se nejprve vola funkce fip a terpve pote se uskutecni pristup pomoci ukazovatka. Pri deklaraci (*pfi)() jsou zavorky navic nutne, protoze podobne jako pri vyhodnoceni vyrazu, se uskutecni nejprve pristup pomoci ukazovatka na funkci, ktera vraci hodnotu typu int. Uvedeme dals priklady: FLOAT fa [17], *afp[17]; Vyse uvedena deklarace deklaruje pole cisel typu float a pole ukazovatek na cisla typu float. Š.po 3 Konecne deklarace: STATIC INT x3d[3][5][7]; deklaruje staticke trirozmerne pole promennych typu int,s celkovym rozmerem 3x5x7. Pole x3d se sklada ze tri polozek, kazda tato polozka je polem, ktere se sklada z peti polozek, ktere jsou take poli, ktera maji 7 polozek typu int. Ve vyra- zech se muze vyskytovat libovolny z nasledujicich vyrazu, ktere odkazuji na dane pole: x3d, x3d[i], x3d[i][j], x3d[i][j][k]. Prve tri maji typ "array" a posledni ma typ int. 8.5 Deklarace struktur a unionu -------------------------------- Struktura je objekt skladajici se z rady pojmenovanych po- lozek. Kazda polozka muze mit libovolny typ. Union je objekt, ktery muze mit v danem okamziku jeden z vice libovolnych typu. Struktury a uniony se specifikuji tou samou formou. specifikator_struktury nebo unionu: struktura/union {seznam_struktury} struktura/union identifikator {seznam_struktury} struktura/union identifikator struktura/union: STRUCT UNION Seznam_struktury je rada deklaraci pro jednotlive cleny struk- tury nebo unionu. seznam_struktury: deklarace_struktury deklarace_struktury seznam_struktury deklarace_struktury: specifikator_typu seznam_ deklaratoru; seznam_deklaratoru: deklarator_struktury deklarator_struktury, seznam_deklaratoru V obvyklem pripade je deklarator_struktury obycejnym deklara- torem jednoduche struktury nebo unionu. Struktura se muze ale take skladat ze specifikovaneho poctu bitu. Takova polozka se nazyva "pole bitu". Jeho velikost je dana konstantnim vyra- zem, ktery je od nazvu pole bitu oddelen znakem ":". deklarator_struktury: deklarator deklarator: konstantni_vyraz : konstantni vyraz Objekty uvnitr struktury jsou umisteny na adresy podle toho, jake je jejich poradi v deklaraci struktury, a to tak, ze Š.po 12 objekty, ktere jsou v deklaraci vice vpravo, maji vyssi adre- sy. Kazdy clen struktury, ktery neni polem bitu je umisten na adresu podle sveho typu. Proto mohou vzniknout uvnitr struktury mista, ktera nejsou prirazena zadne promenne. Pole bitu jsou zarovnany do objektu typu int. Jedno pole bitu nesmi byt nikdy soucasne umisteno ve dvou takovych objektech. Pole bitu, ktere se nevejde do prostoru, ktery v jiz pouzi- tem objektu typu int zbyva, je umisteno cele do dalsich objek- tu. Zadne pole bitu nemuze byt vetsi nezli je objekt typu int, ktery je dan technickymi prostredky vypocetnho systemu. Pole bitu jsou objektum typu int prirazovana zprava doleva na sys- temu PDP-11 a zleva doprava na ostatnich vyse uvedenych vypo- cetnich systemech. Deklarator_struktury, ktery se sklada pouze ze znaku ":" a definice velikosti pole bitu ustanovuje nepojmenovane pole ktere muze byt pouzito pro uspokojeni pozadavku, ktere jsou dany vnejsim vybavenim systemu. Specialnim pripadem je pole bitu delky 0. Takova definice vynuti umisteni dalsiho po- le bitu na pocatku noveho objektu typu int. Normalni cleny struktury, tj. nikoliv pole bitu, se vzdy umistuji od pocat- ku objektu typu int. Jazyk C nedefinuje, jakeho typu maji byt pole bitu, ale na implementacich jazyka C neni pozadovano, aby dovolovaly jina pole bitu, nez celociselneho typu. Tato pole mohou byt vsak povazovana za pole typu unsigned. Na systemu PDP-11 jsou pole bitu implementovana jako promenne typu int unsigned. Ve vsech vyse uvedenych implementacich neexistuji pole poli bitu a adresovy operator "&" nemuze byt na pole bitu aplikovan, ani nemohou existovat ukazovatka na pole bitu. Union predstavuje ve sve podstate strukturu, jejiz vsechny cleny pocinaji na te same adrese/relativni adresa od pocatku unionu je vzdy rovna 0/ a velikost unionu je vzdy takova, aby byla dostatecna i pro nejrozmernejsiho clena unionu. V jedinem okamziku muze byt v unionu ulozen pouze jediny clen jeho struk- tury. Specifikator struktury nebo unionu, ktery ma nasledujici formu: STRUCT identifikator seznam_struktury UNION identifikator seznam_struktury deklaruje identifikator, jako tzv. znacku struktury /znacku unionu/, ktera je specifikovana danym seznamem struktury. Dalsi deklarace jiz mohou pouzivat treti formu specifikace struktury nebo unionu: STRUCT identifikator UNION identifikator Znacky struktury umoznuji definovat struktury, ktere se odka- zuji na sebe same. Jejich vyhoda spociva take v tom, ze dovolu- ji, aby dlouhe definice struktury byly zapsany pouze jedinkrat a posleze pouzity vicekrat. Je zakazano deklarovat struktury nebo uniony, ktere mohou obsahovat samy sebe, ale je mozne deklarovat struktury nebo uniony, ktere obsahuji ukazovatka na sebe sama. Š.po 3 Nazvy clenu struktury nebo nazev znacky struktury je vytvo- ren podle stejnych pravidel jaka plati pro nazvy promennych. Nicmene nazev znacky struktury musi byt rozdilny od nazvu clenu struktury. Dve struktury mohou mit spolecne pocatecni polozky, tj. ty same cleny se mohou vyskytovat ve dvou rozdilnych strukturach, jestlize jsou tehoz typu a vsechny predchazejici polozky jsou totozne. Ve skutecnosti prekladac kontroluje, zdali totozna jmena ve dvou rozdilnych strukturach jsou tehoz typu a maji stejne relativni posunuti od pocatku struktury. Pokud jsou predchazejici cleny struktury rozdilne, neni takova konstrukce prenositelna. Nasleduje jednoduchy priklad deklarace struktury: STRUCT tnode{ CHAR tword[20]; INT count; STRUCT tnode *left; STRUCT tnode *rignt; }; Tato struktura obsahuje znakove pole o 20 znacich, celocisel- nou promennou typu int a dve ukazovatka na tutez strukturu. Jakmile je jednou takova struktura definovana, je mozne ji pou- zit v dalsich deklaracich: STRUCT tnode s,*sp; Vyse uvedena deklarace deklaruje strukturu s s vyse jiz uvede- nou strukturou a ukazovatko sp, ktere ukazuje na strukturu vyse jiz uvedene struktury. S vyuzitim jiz vyse uvedenych deklaraci potom nasledujici vy- raz: sp -> count; urcuje polozku count struktury, ktera je urcena ukazovatkem sp. s.left Tento vyraz urcuje ukazovatko, ktere urcuje levou vetev struk- tury s. s.right -> tword[0]; V tomto vyrazu ukazovatko prave vetve struktury s ukazuje na prvni clen polozky tword dane struktury. 8.6 Inicializace ----------------- Pri deklaraci je mozne specifikovat pocatecni hodnoty jedno- tlivych promennych, ktere jsou deklarovany. Inicializator po- cina znakem "=" a sestava se z vyrazu nebo seznamu hodnot uza- vrenych mezi zavorky. Š.po 12 Inicializator: = vyraz = (seznam_inicializaci) = (seznam inicializaci,) Seznam_inicializaci: vyraz seznam_inicializaci,seznam_inicializaci (seznam_inicializaci) Vsechny inicalizace statickych nebo externich promennych mu- si byt slozeny z konstantnich vyrazu /viz. odstavec c. 15/ nebo vyrazu, ktere urcuji adresu jiz drive deklarovane promenne, pripadne jeji relativni umisteni a konstantni vyraz. Automa- ticke nebo registrove promenne mohou byt inicializovany vyrazy obsahujici konstanty a jiz drive deklarovane promenne a fun- kce. Staticke a externi promenne, ktere nejsou inicializovane, maji pocatecni hodnotu rovnu 0. Automaticke a registrove pro- menne, ktere nejsou inicializovane maji pocatecni hodnotu nedefinovanou /nahodnou/. Pokud je inicializovan skalar /ukazovatko nebo objekt ari- tmetickeho typu/, sklada se inicializace z jednoducheho vyra- zu, ktery muze byt uzavren do zavorek. Pocatecni hodnota daneho objektu je urcena timto vyrazem, pri jeho vycisleni se uskutecni stejne konverze jako pri uskutec- neni prirazeni. Pokud deklarovana hodnota je agregat /tj. struktura nebo pole/, inicializator je vytvoren ze seznamu inicializaci jednotlivych polozek agre- gatu oddelenych carkami a uzavrenych mezi zavorky, ktere jsou psany dle vzrustajiciho indexu nebo poradi polozek. Pokud agre- gat obsahuje vcelenene agregaty, mohou se tato pravidla apli- kovat rekurzivne. Jestlize je inicializovano mene polozek nez agregat obsahuje, jsou zbyvajici polozky vyplneny 0. Neni dovoleno inicializovat uniony a automaticke agregaty. Zavorky smi byt vynechany za nasledujicich podminek. Jestli- ze inicializator zacina levou zavorkou, nasledujici seznam inicializaci oddelenych carkami inicializuje agregat. Je chy- bou pokud tento seznam obsahuje vice clenu nezli je polozek agregatu. Naopak, jestlize inicializator nepocina levou zavor- kou jsou inicializovany pouze nezbytne polozky daneho agre- gatu a zbyvajici inicializace jsou ponechany pro inicializaci polozek agregatu, ktereho je vyse mineny agregat. Je take mozne inicializovat podle znaku /char array/ retez- cem. V takovem pripade jednotlive znaky retezce inicializuji jednotlive polozky znakoveho pole. Nasledujici priklady na inicializace: INT x[] = (1, 3, 5); Uvedeny prikaz deklaruje a inicializuje x jako jednorozmerne pole, ktere ma tri cleny urcene poctem inicializaci. .pa Š.po 3 FLOAT y[4][3] = ( (1, 3, 5), (2, 4, 6), (3, 5, 7), ); Uvedena inicalizace plne vyuziva zavorek. Hodnoty 1, 3 a 5 inicializuji prvni radku pole y 0 /jmenovite polozky y[0][0], y[0][1], y[0][2]. Podobne jsou inicializovany i dve nasledujici radky pole y[1] a y[2]. Protoze inicializace je zakoncena predcasne, je posledni radka pole inicializovana hodnotami 0. Totez je mozne uskutecnit nasledovne: FLOAT y[4][3] = ( 1, 3, 5, 2, 4, 6, 3, 5, 7 ); Inicializace pro pole y pocina levou zavorkou, ale inicializace pro radku y[0] nikoliv, proto jsou pouzity pri inicializaci ze seznamu. Podobne dalsi tri jsou pouzity pro inicalizaci y[1] a dalsi tri pro inicializaci y[2]. FLOAT y[4][3] =( (1), (2), (3), (4) ); Tato inicializace inicializuje prvni sloupec pole y /jedna se o dvourozmerne pole/ a zbyvajici sloupce pole vyplni hodnotami 0. CHAR msg[] = "Syntax error on line %s\n"; Zde se jedna o inicializaci pole retezcem znaku. 8.7 Nazvy typu --------------- Nazvy typu dat je nutne uvadet ve dvou kontextech. Pri spe- cifikaci typu konverze v konstrukci cast a jako argument opera- toru SIZEOF. Je to mozne pouzitim nazvu typu, coz je v podstate cast deklarace typu objektu, ve kterem chybi jmeno vlastniho objektu. Jmeno typu: specifikace_typu abstraktni_deklarator Abstraktni_deklarator: prazdny (abstraktni_deklarator) *abstraktni_deklarator abstraktni_deklarator() abstraktni_deklarator [konstantni_vyraz???] Aby nedoslo ke dvojznacnosti v konstrukci typu: Š.po 12 (abstraktni_deklarator) je pozadovano, aby v teto konstrukci nebyl abstraktni_deklara- tor prazdny. S timto omezenim je mozne vytvorit stejne konstru- kce s abstraktnim deklaratorem, jako kdyby se jednalo o skutec- ny deklarator pri deklaraci. Typ teto konstrukce je stejny jako typ hypotetickeho identifikatoru. Nasledujici priklady: INT INT * INT *[3] INT (*)[3] INT *() INT (*)() Jedna se zde postupne o typy: "integer", "ukazovatko na inte- ger", "pole tri ukazovatek na integer", "ukazovatko na pole tri integer", "funkce vracejici ukazovatko na integer", "ukazo- vatko na funkci vracejici integer". 8.8. TYPEDEF ------------- Deklarace, jejiz trida ulozeni je TYPEDEF ve skutecnosti zadnou pamet neprideluje, namisto toho definuje identifikator, ktery muze byt pozdeji pouzit jako definice zakladniho ci odvozeneho typu. typedef_name: identifikator Uvnitr typedef deklarace se kazdy identifikator, ktery je sou- casti nektereho deklaratoru, stava pozdeji syntaktickym ekvi- valentem klicoveho slova pojmenujiciho typ, ktery je identifi- katoru prirazen. Stejnym zpusobem jak bylo vysvetleno v odstav- ci c. 8.4. Napriklad: TYPEDEF INT miles, *klicksp; TYPEDEF STRUCT {DOUBLE re, im;} complex; uzite v konstrukcich: miles distance; EXTERN klicksp metricp; complex z, *zp; jsou spravne deklarace. Typ distance je int, typ metricp je "pointer to int", typ z je vyse uvedena struktura a typ zp je ukazovatko na danou strukturu. Konstrukce TYPEDEF nevytvari nove typy, pouze synonyma ty- pu, ktere by mohly byt utvoreny normalnim postupem. Napriklad distance ma uplne stejny typ jako objekt, ktery byl deklarovan s typem int. .pa Š.po 3 9. Prikazy ---------- Prikazy jsou normalne vykonavany v tom poradi, v jakem jsou zapsany. 9.1 Vyrazove prikazy -------------------- Zakladnimi prikazy jsou vyrazove prikazy, ktere maji nasleduji- ci formu: vyraz; Nejcastejsim typem techto prikazu jsou prirazeni nebo funkcni volani. 9.2 Slozene prikazy nebo bloky ------------------------------- Je mozne pouzit nekolik prikazu tam, kde by mel byt pouzit pouze jediny. Je to mozne pomoci slozenych prikazu, ktere jsou take nazyvany bloky. slozeny_vyraz: seznam_deklaraci??? seznam_prikazu??? seznam_deklaraci: deklarace deklarace seznam_deklaraci seznam_prikazu: prikaz prikaz seznam_prikazu Jestlize je nektery z identifikatoru, ktere jsou deklarovany totozny s identifikatorem jiz drive deklarovanym, je vnejsi deklarace behem vykonavani bloku potlacena a po ukonceni bloku opet obnovena. Vsechny inicializace promennych typu auto nebo register jsou vzdy pri opetovnem pristupu do bloku provedeny, pokud je pri- stup uskutecnen na zacatek bloku. Je mozne, ale neni to dobra praxe, prenest rizeni primo doprostred bloku, potom k iniciali- zacim nedojde. Inicializace promennych typu static se uskutecni pouze pri spusteni programu. Uvnitr bloku externi deklarace nerezervuji zadne pametove misto a inicializace neni proto dovolena. 9.3 Podminkove prikazy ----------------------- Podminkove prikazy existuji ve dvouch tvarech: IF(vyraz) prikaz IF(vyraz) ELSE prikaz Š.po 12 V obou pripadech je nejprve vyhodnocen vyraz, jestlize je ruzny od nuly, je vykonan prvni prikaz. V pripade 2. tvaru podminko- veho prikazu se vykona druhy prikaz, jestlize ma vyraz hodnotu 0. Obvykla dvojznacnost konstrukce s else pri vnorenych podminko- vych prikazech je resena tim, ze cast else je spojena vzdy s poslednim prikazem if, ke kteremu dosud zadna cast else nena- lezi. 9.4 Prikaz WHILE ----------------- Prikaz WHILE ma tvar: WHILE(vyraz) prikaz prikaz je opakovane vyhodnocovan dokud je hodnota vyrazu nenu- lova. Test teto hodnoty se uskutecni vzdy pred zapocetim vyko- nani prikazu. 9.5 Prikaz DO -------------- Prikaz DO ma tvar: DO prikaz WHILE(vyraz); Prikaz je opakovane vykonavan dokud hodnota vyrazu neni nulova. Test se provadi vzdy po uskutecneni prikazu. 9.6 Prikaz FOR --------------- Prikaz FOR ma tvar: FOR(vyraz-1??? ; vyraz-2??? ; vyraz-3??? ) prikaz Prikaz FOR je ekvivalentni nasledujicim prikazum: vyraz-1; WHILE(vyraz-2) { prikaz vyraz-3; } To znamena, prvni prikaz inicializuje smycku. Druhy vyraz specifikuje test, ktery se vykona pred kazdym opakovanim a zpusobi ukonceni smycky pokud je hodnota vyrazu rovna 0. Treti vyraz nejcasteji specifikuje inkrementaci, ktera se uskutecni po kazdem opakovani smycky. Libovolny nebo vsechny z vyrazu mohou chybet. Chybejici vyraz-2 zpusobi, ze je prikaz FOR ekvivalentni WHILE(1). .pa Š.po 3 9.7 Prikaz SWITCH ------------------ Prikaz SWITCH zpusobi, ze rizeni programu bude preneseno na jeden z nekolika prikazu v zavislosti na hodnote vyrazu. Prikaz SWITCH ma nasledujici tvar: SWITCH(vyraz) prikaz Pri zpracovani vyrazu se uskutecni obvykle aritmeticke konver- ze, ale vysledna hodnota musi byt typu int. Prikaz je vetsinou slozenym prikazem. Libovolny prikaz uvnitr tohoto prikazu muze byt oznacen nasledujici formou: CASE konstantni_vyraz: Konstantni vyraz musi byt typu int. V jedinem prikazu SWITCH nesmeji mit konstantni vyrazy u ruznych prikazu CASE tutez hod- notu. Konstantni vyrazy jsou definovany v odstavci c. 15. Nejvice jeden prikaz uvnitr prikazu SWITCH muze byt oznacen nasledujici formou: DEFAULT Pri vykonavani prikazu SWITCH je nejprve vyhodnocen vyraz a jeho hodnota je porovnavana s kazdym konstantnim vyrazem, ktery prislusi prikazu CASE. Jestlize je hodnota vyrazu rovna nekte- remu z konstantnich vyrazu je rizeni programu preneseno na pri- kazy, ktere nasleduji za prislusnym prikazem CASE. Jestize hod- nota vyrazu neni rovna zadnemu konstantnimu vyrazu a nektery vyraz je oznacen prikazem DEFAULT, potom je rizeni preneseno na prikazy, ktere nasleduji za prikazem DEFAULT. Jestlize hodnota vyrazu neni rovna zadnemu konstantnimu vyrazu ani zadny prikaz neni oznacen DEFAULT, je rizeni preneseno za prikaz SWITCH. Oznaceni CASE a DEFAULT samy o sobe nemeni rizeni programu, ktery tato oznaceni ignoruje. Pro ukonceni jedne vetve prikazu SWITCh je pak nutne pouzit prikaz BREAK, viz odstavec c. 9.8. Ve vetsine pripadu je prikaz SWITCH prikazem slozenym. Na zacatku takoveho prikazu se mohou vyskytovat deklarace, ale inicializace automatickych i registrovanych promennych je neucinna. 9.8. Prikaz BREAK ----------------- Prikaz BREAK ma tvar: BREAK; Tento prikaz zpusobi ukonceni nejvnitrnejsiho prikazu WHILE, DO, FOR nebo SWITCH. Rizeni programu se prenese bezprostredne za ukonceny prikaz. .pa Š.po 12 9.9 Prikaz CONTINUE -------------------- Prikaz CONTINUE ma tvar: CONTINUE; Tento prikaz zpusobi preneseni rizeni na konec nejvnitrnejsi smycky WHILE, DO, nebo FOR. Podrobneji vysvetleno, v kazdem z nasledujicich prikazu: WHILE(...) DO FOR(...) { { { ... ... ... contin:; contin:; contin:; WHILE(...); } } } je prikaz CONTINUE ekvivalentni prikazu GOTO contin. Prikaz, ktery nasleduje navesti contin je tzv. prazdny prikaz, viz odstavec c. 9.13. 9.10 Prikaz RETURN ------------------- Prikaz RETURN vrati rizeni programu z vnitrku funkce do mista odkud byla tato funkce vyvolana. Ma nasledujici formy: RETURN; RETURN vyraz; V prvem tvaru je vracena hodnota nedefinovana. Ve druhem je hodnota vyrazu vracena te casti programu, ktera danou funkci vyvolala. Jestlize je to nutne, je hodnota vyrazu konverto- vana, jako pri prikazu prirazeni na typ shodny s typem funkce. Preneseni rizeni za konec funkce je ekvivalentni navratu bez zadne vracene hodnoty. 9.11 Prikaz GOTO ----------------- Rizeni programu muze byt nepodminene preneseno pomoci prika- zu GOTO, ktery ma nasledujici formu: GOTO identifikator; Identifikator musi byt navestim /viz odstavec c. 9.12/ umiste- ne v prave vykonane funkci. 9.12 Prikaz navesti -------------------- Libovolny prikaz smi byt oznacen navestim, ktere ma nasledu- jici formu: identifikator: Š.po 3 Tento prikaz zpusobi, ze dany identifikator je deklarovan jako navesti. Hlavni pouziti prikazu navesti je pri pouziti prikazu GOTO. Platnost daneho navesti je omezena na prave vykonavanou funkci, vyjma takove bloky do ni vnorene, kde je tentyz iden- tifikator opet deklarovan. Viz odstavec c. 11. 9.13 Prikaz NULL ---------------- Prikaz NULL ma nasledujici formu: ; Prikaz NULL se pouziva s navestim bezprostredne pred koncem slozeneho prikazu nebo jako prazdne telo prikazu smycky, jako je napriklad prikaz WHILE. 10. Externi definice --------------------- Program v jazyku C obsahuje radu externich definic. Exter- ni definice deklaruji identifikatory, ktere maji tridu ulozeni EXTERN pripadne STATIC a dany typ. Specifikace typu muze byt prazdna /viz odstavec c. 8.2/, v takovem pripade se predpoklada typ int. Rozsah externich definici je po celem souboru, ve kterem se takova definice vyskytne. Syntaxe externich definici je ta sama jako je syntaxe normalnich deklaraci. 10.1 Definice externich funkci ------------------------------- Definice funkce ma nasledujici tvar: definice_funkce: specifikator_deklarace??? deklarator_funkce telo_funkce Jedine specifikace ulozeni, ktere jsou povoleny v specifika- toru_deklarace jsou EXTERN nebo STATIC, podrobneji viz odsta- vec c. 11.2. Deklarator funkce je podobny deklaratoru typu "function returning ..." az na definici seznamu formalnich parametru. deklarator_funkce: deklarator (seznam_parametru???) seznam_parametru: identifikator identifikator, seznam_parametru Telo funkce ma tvar: telo_funkce: seznam_deklaraci slozeny_vyraz Pouze identifikatory ze seznamu_parametru mohou byt deklaro- vany v seznamu_deklaraci. Kazdy identifikator, ktereho typ neni urcen, ma typ int. Jedina trida ulozeni, ktera je dovolena ve Š.po 12 specifikaci, je trida REGISTER. Jestlize je tato trida speci- fikovana, je odpovidajici skutecny parametr zkopirovan, pokud je to mozne, primo do registru vypocetniho systemu vne funkce. Uvedeme jednoduchy priklad kompletni definice funkce: INT max (a, b, c,) INT a, b, c; { INT m; m=(a>b) ? a:b; RETURN((m>c) ? m:c); } Ve vyse uvedenem prikladu je INT specifikator typu funkce, max(a,b,c) je deklarator_funkce, INT a,b,c je seznam_para- metru a {...} je blok, ktery tvori telo funkce. Protoze jazyk C konvertuje vsechny skutecne parametry, kte- ke maji typ FLOAT, na typ DOUBLE, jsou formalni parametry, ktere maji typ FLOAT, schopne cist parametry typu DOUBLE. Protoze vsechny odkazy na pole jsou chapany jako odkazy na prvni prvek takoveho pole, deklarace formalniho paramet- ru jako "array of ..." je takova deklarace chapana jako deklarace parametr s typem "pointer to ...". Protoze struk- tury, uniony a funkce nemohou byt funkcemi jako parametry akceptovany, nemohou byt formalni parametry deklarovany s ty- pem struktury, unionu nebo funkce. Samozrejme je dovoleno deklarovat ukazovatka na takove typy. 10.2 Externi definice dat -------------------------- Definice externich dat ma nasledujici formu: definice_dat: deklarace Trida ulozeni externich dat muze byt EXTERN nebo STATIC, ale nesmi byt AUTO nebo REGISTER. Pri neuvedeni tridy ulozeni se predpoklada trida EXTERN.