i != (ne ravno) v tochnosti analogichny operaciyam otnosheniya, za isklyucheniem togo, chto oni imeyut bolee nizkij uroven' starshinstva. (poetomu znachenie vyrazhe- niya a<b==c<d ravno 1 vsyakij raz, kogda vyrazheniya a<b i c<d imeyut odinakovoe znachenie istinnosti). Ukazatel' mozhno sravnivat' s celym, no rezul'tat budet mashinno-nezavisimym tol'ko v tom sluchae, esli celym yavlyaetsya konstanta 0. Garantiruetsya, chto ukazatel', kotoromu prisvo- eno znachenie 0, ne ukazyvaet ni na kakoj ob容kt i na samom dele okazyvaetsya ravnym 0; obshcheprinyato schitat' takoj ukaza- tel' nulem. 4.8. Pobitovaya operaciya 'i' vyrazhenie_i: vyrazhenie & vyrazhenie Operaciya & yavlyaetsya associativnoj, i vklyuchayushchie & vyrazheniya mogut byt' pereuporyadocheny kompilyatorom. Vypolnyayutsya obych- nye arifmeticheskie preobrazovaniya; rezul'tatom yavlyaetsya pobitovaya funkciya 'i' operandov. |ta operaciya primenima tol'ko k operandam celogo tipa. 4.9. Pobitovaya operaciya isklyuchayushchego 'ili' vyrazhenie_isklyuchayushchego_ili: vyrazhenie ^ vyrazhenie Operaciya ^ (znak nadcherkivaniya, kod v KOI-8 0136) yavlyaetsya associativnoj, i vklyuchayushchie ^ vyrazheniya mogut byt' pereupo- ryadocheny kompilyatorom. Vypolnyayutsya obychnye arifmeticheskie preobrazovaniya; rezul'tatom yavlyaetsya pobitovaya funkciya isk- lyuchayushchego 'ili' operandov. Operaciya primenima tol'ko k ope- randam celochislennogo tipa. 4.10. Pobitovaya operaciya vklyuchayushchego 'ili' vyrazhenie_vklyuchayushchego_ili: vyrazhenie | vyrazhenie -17- Operaciya | yavlyaetsya associativnoj, i soderzhashchie | vyrazheniya mogut byt' pereuporyadocheny. Vypolnyayutsya obychnye arifmetiches- kie preobrazovaniya; rezul'tatom yavlyaetsya pobitovaya funkciya vklyuchayushchego 'ili' operandov. Operaciya primenima tol'ko k operandam celochislennogo tipa. 4.11. Logicheskaya operaciya 'i' vyrazhenie_logicheskogo_i: vyrazhenie && vyrazhenie Operaciya && gruppiruetsya sleva napravo. Ona vozvrashchaet 1, esli oba ee operanda otlichny ot nulya, i 0 v protivnom slu- chae. V otlichie ot & operaciya && garantiruet vychislenie sleva napravo; bolee togo, esli pervyj operand raven 0, to znache- nie vtorogo operanda voobshche ne vychislyaetsya. Operandy ne obyazany byt' odinakovogo tipa, no kazhdyj iz nih dolzhen byt' libo odnogo iz osnovnyh tipov, libo ukazate- lem. Rezul'tat vsegda imeet tip int. 4.12. Operaciya logicheskogo 'ili' vyrazhenie_logicheskogo_ili: vyrazhenie || vyrazhenie Operaciya || gruppiruetsya sleva napravo. Ona vozvrashchaet 1, esli odin iz operandov otlichen ot nulya, i 0 v protivnom slu- chae. V otlichie ot operacii | operaciya || garantiruet vychis- lenie sleva napravo; bolee togo, esli pervyj operand otlichen ot nulya, to znachenie vtorogo operanda voobshche ne vychislyaetsya. Operandy ne obyazany byt' odinakovogo tipa, no kazhdyj iz nih dolzhen byt' libo odnogo iz osnovnyh tipov, libo ukazate- lem. Rezul'tat vsegda imeet tip int. 4.13. Uslovnaya operaciya uslovnoe_vyrazhenie: vyrazhenie ? vyrazhenie : vyrazhenie Uslovnye vyrazheniya gruppiruyutsya sleva napravo. Vychislyaetsya znachenie pervogo vyrazheniya, i esli ono otlichno ot nulya, to rezul'tatom budet znachenie vtorogo vyrazheniya; v protivnom sluchae rezul'tatom budet znachenie tret'ego vyrazheniya. Esli eto vozmozhno, provodyatsya obychnye arifmeticheskie preobrazova- niya, s tem, chtoby privesti vtoroe i tret'e vyrazheniya k obshchemu tipu; v protivnom sluchae, esli oba vyrazheniya yavlyayutsya ukazatelyami odinakovogo tipa, to rezul'tat imeet tot zhe tip; v protivnom sluchae odno vyrazhenie dolzhno byt' ukazatelem, a drugoe - konstantoj 0, i rezul'tat budet imet' tip ukaza- telya. Vychislyaetsya tol'ko odno iz vtorogo i tret'ego vyrazhe- nij. -18- 4.14. Operaciya prisvaivaniya Imeetsya ryad operacij prisvaivaniya, kazhdaya iz kotoryh gruppiruetsya sleva napravo. Vse operacii trebuyut v kachestve svoego levogo operanda l_znachenie, a tipom vyrazheniya prisva- ivaniya yavlyaetsya tip ego levogo operanda. Znacheniem vyrazheniya prisvaivaniya yavlyaetsya znachenie, hranimoe v levom operande posle togo, kak prisvaivanie uzhe budet proizvedeno. Dve chasti sostavnoj operacii prisvaivaniya yavlyayutsya otdel'nymi leksemami. vyrazhenie_prisvaivaniya: l_znachenie = vyrazhenie l_znachenie += vyrazhenie l_znachenie -= vyrazhenie l_znachenie *= vyrazhenie l_znachenie /= vyrazhenie l_znachenie %= vyrazhenie l_znachenie >>= vyrazhenie l_znachenie <<= vyrazhenie l_znachenie &= vyrazhenie l_znachenie ^= vyrazhenie l_znachenie |= vyrazhenie Kogda proizvoditsya prostoe prisvaivanie '=', znachenie vyrazheniya zamenyaet znachenie ob容kta, na kotoroe ssylaetsya l_znachenie. Esli oba operanda imeyut arifmeticheskij tip, to pered prisvaivaniem pravyj operand preobrazuetsya k tipu levogo operanda. V vyrazhenie vida e1 op= e2, gde op - odna iz perechis- lennyh vyshe operacij, ekvivalentno vyrazheniyu e1 = e1 op (e2), s tem otlichiem, chto vyrazhenie e1 vychislya- etsya tol'ko odin raz. V sluchae operacij += i -= levyj ope- rand mozhet byt' ukazatelem, prichem pri etom (celochislennyj) pravyj operand preobrazuetsya takim obrazom, kak ob座asneno v p. 0.4; vse pravye operandy i vse otlichnye ot ukazatelej levye operandy dolzhny imet' arifmeticheskij tip. Ispol'zuemye v OS DEMOS kompilyatory dopuskayut prisvai- vanie ukazatelya celomu, celogo ukazatelyu i ukazatelya ukaza- telyu drugogo tipa. Takoe prisvaivanie yavlyaetsya chistym kopi- rovaniem bez kakih-libo preobrazovanij. Takoe upotreblenie operacij prisvaivaniya yavlyaetsya neperenosimym i mozhet privo- dit' k ukazatelyam, kotorye pri ispol'zovanii vyzyvayut oshibki adresacii. Tem ne menee garantiruetsya, chto prisvaivanie uka- zatelyu konstanty 0 daet nulevoj ukazatel', kotoryj mozhno otlichat' ot ukazatelya na lyuboj ob容kt. -19- 4.15. Prisvaivanie struktury Struktury mogut byt' prisvoeny, a takzhe peredany funk- ciyam v kachestve argumentov i vozvrashcheny funkciyami. Tipy uchastvuyushchih operandov dolzhny sovpadat'. 4.16. Operaciya 'zapyataya< vyrazhenie_s_zapyatoj: vyrazhenie , vyrazhenie Para vyrazhenij, razdelennyh zapyatoj, vychislyaetsya sleva nap- ravo i znachenie levogo vyrazheniya otbrasyvaetsya. Tipom i zna- cheniem rezul'tata yavlyaetsya tip i znachenie pravogo operanda. |ta operaciya gruppiruetsya sleva napravo. V kontekste, gde zapyataya imeet special'noe znachenie, kak, naprimer, v spiske fakticheskih argumentov funkcij ili v spiskah inicializato- rov, operaciya zapyataya, opisyvaemaya v etom razdele, mozhet poyavlyat'sya tol'ko v kruglyh skobkah; naprimer, funkciya f(a,(t=3,t+2),c) imeet tri argumenta, vtoroj iz kotoryh imeet znachenie 5. 4.17. Starshinstvo i poryadok vychisleniya. V privodimoj nizhe tablice svedeny pravila starshinstva i associativnosti vseh operacij. Operacii, raspolozhennye v odnoj stroke, imeyut odin i tot zhe uroven' starshinstva; stroki raspolozheny v poryadke ubyvaniya starshinstva. Tak, nap- rimer, operacii *, "/" i "%" imeyut odinakovyj uroven' star- shinstva, kotoryj vyshe, chem uroven' operacij "+" i "-". -20- Tablica 2 ------------------------------------------ | Operator | Associativnost' | |____________________|___________________| | () [] -> . | sleva napravo | |____________________|___________________| | ~ ++ -- - f | sprava nalevo | |(type) * & sizeof| | |____________________|___________________| | * / % | sleva napravo | |____________________|___________________| | + - | sleva napravo | |____________________|___________________| | << >> | sleva napravo | |____________________|___________________| | < <= > >= | sleva napravo | |____________________|___________________| | == != | sleva napravo | |____________________|___________________| | & | sleva napravo | |____________________|___________________| | ^ | sleva napravo | |____________________|___________________| | | | sleva napravo | |____________________|___________________| | && | sleva napravo | |____________________|___________________| | || | sleva napravo | |____________________|___________________| | ?: | sprava nalevo | |____________________|___________________| | = += -= i t.p. | sprava nalevo | |____________________|___________________| | , | sleva napravo | |____________________|___________________| Otmetim, chto uroven' starshinstva pobitovyh logicheskih operacij &, ^ i | nizhe urovnya operacij == i !=. |to privodit k tomu, chto osushchestvlyayushchie pobitovuyu proverku vyrazheniya, podobnye if ((h & mask) == 0) ... dlya polucheniya pravil'nyh rezul'tatov dolzhny zaklyuchat'sya v kruglye skobki, v protivnom sluchae ono budet ponyato tak: vyrazhenie: x & mask == 0 ponyato kak: x & ( mask == 0 ) -21-  * 5. OPISANIYA Opisaniya ispol'zuyutsya dlya ukazaniya interpretacii, koto- ruyu yazyk Si budet davat' kazhdomu identifikatoru; oni ne obya- zatel'no rezerviruyut pamyat', sootvetstvuyushchuyu identifikatoru. Opisaniya imeyut formu opisanie: specifikatory_opisaniya spisok_opisatelej; neob Opisateli v spiske opisatelej soderzhat opisyvaemye identifi- katory. Specifikatory opisaniya predstavlyayut soboj posledo- vatel'nost' specifikatorov tipa i specifikatorov klassa pamyati. specifikatory_opisaniya: s_tipa s_opisaniya neob s_klassa_pamyati s_opisaniya neob gde c_... - specifikator_... Spisok opisatelej dolzhen byt' soglasovannym v smysle, opisy- vaemom nizhe. 5.1. Specifikatory klassa pamyati nizhe perechislyayutsya specifikatory klassa pamyati: specifikator_klassa_pamyati: auto static extern register typedef Specifikator typedef ne rezerviruet pamyat' i nazyvaetsya "specifikatorom klassa pamyati" tol'ko po sintaksicheskim soobrazheniyam; eto obsuzhdaetsya nizhe. Smysl razlichnyh klassov pamyati byl obsuzhden ranee (sm. "Ob容kty yazyka Si"). Opisaniya auto, static i register sluzhat takzhe v kachestve opredelenij v tom smysle, chto oni vyzyvayut rezervi- rovanie nuzhnogo kolichestva pamyati. V sluchae extern dolzhno prisutstvovat' vneshnee opredelenie ukazyvaemyh identifikato- rov gde to vne funkcii, v kotoroj oni opisany. Opisanie register luchshe vsego predstavlyat' sebe kak opisanie auto vmeste s namekom kompilyatoru, chto opisannye takim obrazom peremennye budut chasto ispol'zovat'sya. |ffek- tivny tol'ko neskol'ko pervyh takih opisanij. Krome togo, v -22- registrah mogut hranit'sya tol'ko peremennye opredelennyh tipov; na CM-|VM eto int, char ili ukazatel'. Sushchestvuet i drugoe ogranichenie na ispol'zovanie registrovyh peremennyh: k nim nel'zya primenyat' operaciyu vzyatiya adresa &. Pri razum- nom ispol'zovanii registrovyh opisanij mozhno ozhidat' poluche- niya men'shih po razmeru i bolee bystryh programm, no v budu- shchem uluchshenie generirovaniya kodov mozhet sdelat' ih nenuzh- nymi. V kompilyatore dlya SM |VM vosprinimayutsya pervye 3 opisa- niya register v kazhdoj funkcii. Opisanie mozhet soderzhat' ne bolee odnogo specifikatora klassa pamyati. Esli opisanie ne soderzhit specifikatora klassa pamyati, to schitaetsya, chto on imeet znachenie auto, esli opisanie nahoditsya vnutri nekotoroj funkcii, i extern v protivnom sluchae. Isklyuchenie: funkcii nikogda ne byvayut avtomaticheskimi. 5.2. Specifikatory tipa Nizhe perechislyayutsya specifikatory tipa. specifikator_tipa: char short int long unsigned float double specifikator_struktury_ili_ob容dineniya specifikator_perechisleniya opredelyayushchee_tip_imya Slova long, short i unsigned mozhno rassmatrivat' kak prila- gatel'nye; dopustimy sleduyushchie kombinacii: short int long int unsigned int long float Poslednyaya kombinaciya oznachaet to zhe, chto i double. V ostal'- nom opisanie mozhet soderzhat' ne bolee odnogo specifikatora tipa. Esli opisanie ne soderzhit specifikatora tipa, to schi- taetsya, chto on imeet znachenie int. Specifikatory struktur i ob容dinenij obsuzhdayutsya v p. 0.5, specifikaciya perechislimogo tipa - v p.0.6; opisaniya s opredelyayushchimi tip imenami typedef obsuzhdayutsya v p. 0.9. -23- 5.3. Opisateli Vhodyashchij v opisanie spisok opisatelej predstavlyaet soboj posledovatel'nost' razdelennyh zapyatymi opisatelej, kazhdyj iz kotoryh mozhet imet' inicializator. spisok_opisatelej: inicializiruemyj_opisatel' inicializiruemyj_opisatel',spi- sok_opisatelej inicializiruemyj_opisatel': opisatel' inicializator neob Inicializatory opisyvayutsya v p.0.6. Specifikatory i opisaniya ukazyvayut tip i klass pamyati ob容ktov, na kotorye ssylayutsya opisateli. Opisateli imeyut sleduyushchij sintaksis: opisatel': identifikator ( opisatel' ) * opisatel' opisatel' () opisatel' [konstantnoe-vyrazhenie] neob Gruppirovanie takoe zhe, kak i v vyrazheniyah. 5.4. Smysl opisatelej Kazhdyj opisatel' rassmatrivaetsya kak utverzhdenie togo, chto kogda konstrukciya toj zhe samoj formy, chto i opisatel', poyavlyaetsya v vyrazhenii, to ona vydaet ob容kt ukazannogo tipa i ukazannogo klassa pamyati. Kazhdyj opisatel' soderzhit rovno odin identifikator; eto imenno tot identifikator, kotoryj i opisyvaetsya. Esli v kachestve opisatelya poyavlyaetsya prosto identifika- tor, to on imeet tip, ukazyvaemyj v specificiruyushchem zago- lovke opisaniya. Opisatel' v kruglyh skobkah identichen opisatelyu bez kruglyh skobok, no kruglye skobki mogut izmenyat' svyazi v sostavnyh opisatelyah. Primery smotri nizhe. Predstavim sebe opisanie t di gde t - specifikator tipa (podobnyj int i t.d.), a di - opi- satel'. Predpolozhim, chto eto opisanie privodit k tomu, chto sootvetstvuyushchij identifikator imeet tip ...t, gde "..." pusto, esli di prosto otdel'nyj identifikator (tak chto tip h -24- v int h prosto int). Togda, esli di imeet formu *d to soderzhashchijsya identifikator budet imet' tip ... ukazatel' na t. Esli di imeet formu d() to soderzhashchijsya identifikator imeet tip ... funkciya, vozvra- shchayushchaya t. Esli di imeet formu d[konstantnoe_vyrazhenie] ili d[ ] to soderzhashchijsya identifikator imeet tip ... massiv t. V per- vom sluchae konstantnym vyrazheniem yavlyaetsya vyrazhenie, znache- nie kotorogo mozhno opredelit' vo vremya kompilyacii i kotoroe imeet tip int. (tochnoe opredelenie konstantnogo vyrazheniya dano nizhe). Kogda neskol'ko specifikacij vida "massiv iz" okazyvayutsya primykayushchimi, to sozdaetsya mnogomernyj massiv; konstantnoe vyrazhenie, zadayushchee granicy massivov, mozhet otsutstvovat' tol'ko u pervogo chlena etoj posledovatel'- nosti. Takoe opuskanie polezno, kogda massiv yavlyaetsya vnesh- nim ili formal'nym i ego fakticheskoe opredelenie, kotoroe vydelyaet pamyat', privoditsya v drugom meste. Pervoe konstant- noe vyrazhenie mozhet byt' opushcheno takzhe togda, kogda za opi- satelem sleduet inicializaciya. V etom sluchae razmer oprede- lyaetsya po chislu privedennyh inicializiruemyh elementov. Massiv mozhet byt' obrazovan iz elementov odnogo iz osnovnyh tipov, iz ukazatelej, iz struktur ili ob容dinenij ili iz drugih massivov (chtoby obrazovat' mnogomernyj mas- siv). Ne vse vozmozhnosti, kotorye razresheny s tochki zreniya ukazannogo vyshe sintaksisa, fakticheski dopustimy. Imeyutsya sleduyushchie ogranicheniya: funkcii ne mogut vozvrashchat' massivy ili funkcii, hotya oni mogut vozvrashchat' ukazateli na takie veshchi; ne sushchestvuet massivov funkcij, hotya mogut byt' mas- sivy ukazatelej na funkcii. Analogichno, struktury ili ob容- dineniya ne mogut soderzhat' funkciyu, no oni mogut soderzhat' ukazatel' na funkciyu. V kachestve primera rassmotrim opisanie -25- int i, *ip, f(), *fip(), (*pfi)(); v kotorom opisyvaetsya celoe i, ukazatel' ip na celoe, funk- ciya f, vozvrashchayushchaya celoe, funkciya fip, vozvrashchayushchaya ukaza- tel' na celoe, i ukazatel' pfi na funkciyu, kotoraya vozvra- shchaet celoe. Osobenno polezno sravnit' dva poslednih opisa- telya. Svyaz' v *fip() mozhno predstavit' v vide *(fip()), tak chto opisaniem predpolagaetsya, chto v vyrazhenii trebuetsya obrashchenie k funkcii fip i posleduyushchee ispol'zovanie kosven- noj adresacii dlya vydachi s pomoshch'yu poluchennogo rezul'tata (ukazatelya) celogo. V opisatele (*pfi)() dopolnitel'nye skobki neobhodimy, poskol'ku oni tochno tak zhe, kak i v vyra- zhenii, ukazyvayut, chto kosvennaya adresaciya cherez ukazatel' vydaet funkciyu, kotoraya zatem vyzyvaetsya; eta vyzvannaya funkciya vozvrashchaet celoe. V kachestve drugogo primera privedem opisanie float fa[17], *afp[17]; v kotorom opisyvaetsya massiv chisel tipa float i massiv uka- zatelej na chisla tipa float. Nakonec, static int h3d[3][5][7]; opisyvaet staticheskij trehmernyj massiv celyh razmerom 3*5*7. Bolee podrobno: h3d yavlyaetsya massivom iz treh elemen- tov; kazhdyj element yavlyaetsya massivom pyati massivov; kazhdyj poslednij massiv yavlyaetsya massivom iz semi celyh. Kazhdoe iz vyrazhenij h3d, h3d[i], h3d[i][j] i h3d[i][j][k] mozhet razum- nym obrazom poyavlyat'sya v vyrazheniyah. Pervye tri imeyut tip "massiv", poslednee imeet tip int. 5.5. Opisanie struktur i ob容dinenij Struktura - eto ob容kt, sostoyashchij iz posledovatel'nosti imenovannyh chlenov. Kazhdyj chlen mozhet byt' proizvol'nogo tipa. Ob容dinenie - eto ob容kt, kotoryj v dannyj moment mozhet soderzhat' lyuboj iz neskol'kih chlenov. Specifikatory i ob容dineniya imeyut odinakovuyu formu. specifikator_struktury_ili_ob容dineniya: struktura_ili_ob容dinenie { spi- sok_opisanij_struktury } identifikator_struktury_ili_ob容dine- niya { spisok-opisanij-struktury } identifikator_struktury_ili_ob容dineniya struktura_ili_ob容dinenie: struct union -26- Spisok_opisanij_struktury yavlyaetsya posledovatel'nost'yu opi- sanij chlenov struktury ili ob容dineniya: spisok_opisanij_struktury: opisanie_struktury opisanie_struktury spi- sok_opisanij_struktury opisanie_struktury: specifikator_tipa spi- sok_opisatelej_struktury spisok_opisatelej_struktury: opisatel'_struktury opisatel'_struktury,spisok_opi- satelej_struktury V obychnom sluchae opisatel' struktury yavlyaetsya prosto opisa- telem chlena struktury ili ob容dineniya. CHlen struktury mozhet takzhe sostoyat' iz specificirovannogo chisla bitov. Takoj chlen nazyvaetsya takzhe polem; ego dlina otdelyaetsya ot imeni polya dvoetochiem. opisatel'_struktury: opisatel' opisatel': konstantnoe_vyrazhenie : konstantnoe_vyrazhenie Vnutri struktury opisannye v nej ob容kty imeyut adresa, koto- rye uvelichivayutsya v sootvetstvii s chteniem opisanij ob容ktov sleva napravo. Kazhdyj chlen struktury, kotoryj ne yavlyaetsya polem, nachinaetsya s adresnoj granicy, sootvetstvuyushchej ego tipu; sledovatel'no v strukture mogut okazat'sya neimenovan- nye dyry. CHleny, yavlyayushchiesya polyami, pomeshchayutsya v mashinnye celye; oni ne perekryvayut granicy slova. Pole, kotoroe ne umeshchaetsya v ostavshemsya v dannom slove prostranstve, pomeshcha- etsya v sleduyushchee slovo. Polya vydelyayutsya sprava nalevo na CM-|VM, no mogut vydelyat'sya sleva napravo na drugih mashinah. Opisatel' struktury, kotoryj ne soderzhit opisatelya, a tol'ko dvoetochie i shirinu, ukazyvaet neimenovannoe pole, poleznoe dlya zapolneniya svobodnogo prostranstva s cel'yu sootvetstviya zadavaemym izvne shemam. Special'nyj sluchaj neimenovannogo polya s shirinoj 0 ispol'zuetsya dlya ukazaniya o vyravnivanii sleduyushchego polya na granicu slova. Pri etom predpolagaetsya, chto "sleduyushchee pole" dejstvitel'no yavlyaetsya polem, a ne obychnym chlenom struktury, poskol'ku v poslednem sluchae vyravnivanie osushchestvlyaetsya avtomaticheski. Sam yazyk ne nakladyvaet ogranichenij na tipy ob容ktov, opisannyh kak polya, no ot realizacij ne trebuetsya obespechi- vat' chto-libo otlichnoe ot celyh polej. Bolee togo, dazhe polya -27- tipa int mogut rassmatrivat'sya kak ne imeyushchie znaka. Na CM- |VM polya ne imeyut znaka i mogut prinimat' tol'ko celye zna- cheniya. Vo vseh realizaciyah otsutstvuyut massivy polej i k polyam ne primenima operaciya vzyatiya adresa &, tak chto ne sushchestvuet i ukazatelej na polya. Ob容dinenie mozhno predstavit' sebe kak strukturu, vse chleny kotoroj nachinayutsya so smeshcheniya 0 i razmer kotoroj dos- tatochen, chtoby soderzhat' lyuboj iz ee chlenov. V kazhdyj moment ob容dinenie mozhet soderzhat' ne bolee odnogo iz svoih chlenov. Specifikator struktury ili ob容dineniya vo vtoroj forme, t.e. odin iz: struct ident {spisok_opisanij_struktury} union ident {spisok-opisanij-struktury} opisyvaet ident v kachestve yarlyka struktury (ili yarlyka ob容dineniya) dlya struktury, specificirovannoj etim spiskom. Posleduyushchee opisanie mozhet zatem ispol'zovat' tret'yu formu specifikatora, odin iz struct ident union ident YArlyki struktur dayut vozmozhnost' opredeleniya struktur, koto- rye ssylayutsya na samih sebya; oni takzhe pozvolyayut neodnok- ratno ispol'zovat' privedennuyu tol'ko odin raz dlinnuyu chast' opisaniya. Zapreshchaetsya opisyvat' strukturu ili ob容dinenie, kotorye soderzhat obrazec samogo sebya, no struktura ili ob容- dinenie mogut soderzhat' ukazatel' na strukturu ili ob容dine- nie takogo zhe vida, kak oni sami. Imena chlenov i yarlykov struktur mogut sovpadat' s ime- nami obychnyh peremennyh. Odnako imena yarlykov i chlenov dolzhny byt' vzaimno razlichnymi. Dve struktury mogut imet' obshchuyu nachal'nuyu posledova- tel'nost' chlenov; eto oznachaet, chto tot zhe samyj chlen mozhet poyavit'sya v dvuh razlichnyh strukturah, esli on imeet odina- kovyj tip v obeih strukturah i esli vse predydushchie chleny obeih struktur odinakovy. Fakticheski kompilyator tol'ko pro- veryaet, chto imya v dvuh razlichnyh strukturah imeet odinakovyj tip i odinakovoe smeshchenie, no esli predshestvuyushchie chleny otlichayutsya, to konstrukciya okazyvaetsya neperenosimoj. Vot prostoj primer opisaniya struktury: -28- struct tnode { char tword[20]; int count; struct tnode *left; struct tnode *right; }; takaya struktura soderzhit massiv iz 20 simvolov, celoe i dva ukazatelya na takie zhe struktury. Kak tol'ko privedeno takoe opisanie, opisanie struct tnode s, *sp; govorit o tom, chto s yavlyaetsya strukturoj ukazannogo vida, a sp yavlyaetsya ukazatelem na strukturu ukazannogo vida. Pri nalichii etih opisanij vyrazhenie sp->count ssylaetsya na pole count struktury, na kotoruyu ukazyvaet sp; vyrazhenie s.left ssylaetsya na ukazatel' levogo poddereva v strukture s, a vyrazhenie s.right->tword[0] ssylaetsya na pervyj simvol chlena tword pravogo poddereva iz s. 5.6. Perechislimyj tip Perechislimyj tip dannyh analogichen skalyarnym tipam yazyka Paskal'. Specifikator perechislimogo tipa imeet sledu- yushchij vid: specifikator_perechisleniya: enum spisok_perechisleniya enum identifikator spisok_perechisleniya enum identifikator spisok_perechisleniya: perechislyaemoe spisok_perechisleniya, perechislyaemoe perechislyaemoe: identifikator identifikator = konstantnoe vyrazhenie -29- Rol' identifikatora v specifikatore_perechisleniya pol- nost'yu analogichna roli yarlyka struktury v specifikatore_struktury; identifikator oboznachaet opredelen- noe perechislenie. Naprimer, opisanie enum color {red, white, black, blue }; . . . enum color *cp, col; ob座avlyaet identifikator color yarlykom perechisleniya tipa, opisyvayushchego razlichnye cveta i zatem ob座avlyaet cr ukazatelem na ob容kt etogo tipa, a col - ob容ktom etogo tipa. Identifikatory v spiske_perechisleniya stanovyatsya kons- tantami i mogut poyavlyat'sya tam, gde trebuyutsya (po kontekstu) konstanty. Esli ne ispol'zuetsya vtoraya forma perechislyaemogo (s ravenstvom =), to velichiny konstant nachinayutsya s 0 i voz- rastayut na 1 v sootvetstvii s prochteniem ih opisaniya sleva napravo. Perechislyaemoe s prisvoeniem = pridaet sootvetstvuyu- shchemu identifikatoru ukazannuyu velichinu; posleduyushchie identi- fikatory prodolzhayut progressiyu ot pripisannoj velichiny. YArlyki perechislenij i imena konstant dolzhny byt' raz- lichnymi i ne sovpadat' s imenami yarlykov i chlenov struktur. Ob容kty dannogo tipa perechisleniya rassmatrivayutsya kak ob容kty, imeyushchie tip, otlichnyj ot lyubyh tipov i kontroliruyu- shchaya programma lint soobshchaet ob oshibkah nesootvetstviya tipov. V realizacii na CM_|VM so vsemi perechislyaemymi peremennymi operiruyut tak, kak esli by oni imeli tip int. 5.7. Inicializaciya Opisatel' mozhet ukazyvat' nachal'noe znachenie opisyvae- mogo identifikatora. Inicializator sostoit iz vyrazheniya ili zaklyuchennogo v figurnye skobki spiska znachenij, pered koto- rymi stavitsya znak =. inicializator: = vyrazhenie = {spisok_inic} = {spisok_inic,} spisok_inic: vyrazhenie spisok_inic,spisok_inic {spisok_inic} gde spisok_inic - spisok_inicializatorov -30- Vse vyrazheniya, vhodyashchie v inicializator staticheskoj ili vneshnej peremennoj, dolzhny byt' libo konstantnymi vyrazheni- yami, libo vyrazheniyami, kotorye svodyatsya k adresu ranee opi- sannoj peremennoj, smeshchennomu na konstantnoe (vozmozhno, nulevoe) vyrazhenie. Avtomaticheskie i registrovye peremennye mogut byt' inicializirovany proizvol'nymi vyrazheniyami, vklyu- chayushchimi konstanty i ranee opisannye peremennye i funkcii. Garantiruetsya, chto neinicializirovannye staticheskie i vneshnie peremennye poluchayut v kachestve nachal'nyh znachenij 0; neinicializirovannye avtomaticheskie i registrovye peremennye v kachestve nachal'nyh znachenij soderzhat musor. Kogda inicializator primenyaetsya k skalyaru (ukazatelyu ili ob容ktu arifmeticheskogo tipa), to on sostoit iz odnogo vyrazheniya, vozmozhno zaklyuchennogo v figurnye skobki. Nachal'- noe znachenie ob容kta nahoditsya iz vyrazheniya; vypolnyayutsya te zhe samye preobrazovaniya, chto i pri prisvaivanii. Kogda opisyvaemaya peremennaya yavlyaetsya agregatom (struk- turoj ili massivom), to inicializator sostoit iz zaklyuchen- nogo v figurnye skobki i razdelennogo zapyatymi spiska inici- alizatorov dlya chlenov agregata. |tot spisok sostavlyaetsya v poryadke vozrastaniya indeksa ili v sootvetstvii s poryadkom chlenov. Esli agregat soderzhit podagregaty, to eto pravilo primenyaetsya rekursivno k chlenam agregata. Esli kolichestvo inicializatorov v spiske okazyvaetsya men'she chisla chlenov agregata, to ostavshiesya chleny agregata zapolnyayutsya nulyami. Zapreshchaetsya inicializirovat' ob容dineniya ili avtomaticheskie agregaty. Figurnye skobki mogut interpretirovat'sya sleduyushchim obrazom. Esli inicializator nachinaetsya s levoj figurnoj skobki, to posleduyushchij razdelennyj zapyatymi spisok iniciali- zatorov inicializiruet chleny agregata; budet oshibkoj, esli v spiske okazhetsya bol'she inicializatorov, chem chlenov agregata. Esli odnako inicializator ne nachinaetsya s levoj figurnoj skobki, to iz spiska beretsya tol'ko nuzhnoe dlya chlenov dan- nogo agregata chislo elementov; ostavshiesya elementy ispol'zu- yutsya dlya inicializacii sleduyushchego chlena agregata, chast'yu kotorogo yavlyaetsya nastoyashchij agregat. Sledovatel'no, skobki v nekotoryh sluchayah mozhno opuskat'. Poslednee sokrashchenie dopuskaet vozmozhnost' inicializa- cii massiva tipa char s pomoshch'yu stroki. V etom sluchae chleny massiva posledovatel'no inicializiruyutsya simvolami stroki. Naprimer, int h[] = {1,3,5}; opisyvaet i inicializiruet h kak odnomernyj massiv; pos- kol'ku razmer massiva ne specificirovan, a spisok -31- inicializatora soderzhit tri elementa, schitaetsya, chto massiv sostoit iz treh chlenov. Vot primer inicializacii s polnym ispol'zovaniem figur- nyh skobok: float *y[4][3] = { ( 1, 3, 5 ), ( 2, 4, 6 ), ( 3, 5, 7 ), }; Zdes' 1, 3 i 5 inicializiruyut pervuyu stroku massiva y[0], a imenno y[0][0], y[0][1] i y[0][2]. Analogichnym obrazom sle- duyushchie dve strochki inicializiruyut y[1] i y[2]. Inicializator zakanchivaetsya prezhdevremenno, i, sledovatel'no, massiv y[3] inicializiruetsya nulyami. V tochnosti takogo zhe effekta mozhno bylo by dostich', napisav float y[4][3] = { 1, 3, 5, 2, 4, 6, 3, 5, 7 }; Inicializator dlya y nachinaetsya s levoj figurnoj skobki, no inicializatora dlya y[0] net. Poetomu ispol'zuetsya 3 elementa iz spiska. Analogichno sleduyushchie tri elementa ispol'zuyutsya posledovatel'no dlya y[1] i y[2]. Sleduyushchee opisanie float y[4][3] = { {1}, {2}, {3}, {4} }; inicializiruet pervyj stolbec y (esli ego rassmatrivat' kak dvumernyj massiv), a ostal'nye elementy zapolnyayutsya nulyami. I nakonec, opisanie char msg[] = "syntax error on line %s\n"; demonstriruet inicializaciyu elementov simvol'nogo massiva s pomoshch'yu stroki. 5.8. Imena tipov V dvuh sluchayah (dlya yavnogo ukazaniya tipa preobrazovaniya v konstrukcii perevoda i dlya argumentov operacii sizeof) zhelatel'no imet' vozmozhnost' zadavat' tip dannyh. |to osu- shchestvlyaetsya s pomoshch'yu "imeni tipa", kotoroe po sushchestvu yavlyaetsya opisaniem ob容kta takogo tipa, v kotorom opushcheno imya samogo ob容kta. -32- Imya tipa: specifikator_tipa abstraktnyj_opisatel' abstraktnyj_opisatel': pusto (abstraktnyj_opisatel') *abstraktnyj opisatel' abstraktnyj_opisatel' () abstraktnyj_opisatel' [konstant- noe vyrazhenie] neob Vo izbezhanie dvusmyslennosti v konstrukcii (abstraktnyj_opisatel') trebuetsya, chtoby abstraktnyj_opisatel' byl nepust. Pri etom ogranichenii vozmozhno odnoznachno opredelit' to mesto v abstraktnom_opisatele, gde dolzhen poyavit'sya identifikator, esli by eta konstrukciya byla opisatelem v opisanii. Imeno- vannyj tip sovpadaet togda s tipom gipoteticheskogo identifi- katora. Naprimer, imena tipov int int * int *[3] int (*)[3] int *() int (*)() imenuyut sootvetstvenno tipy "celyj", "ukazatel' na celoe", "massiv iz treh ukazatelej na celoe", "ukazatel' na massiv iz treh celyh", " funkciya, vozvrashchayushchaya ukazatel' na celoe" i "ukazatel' na funkciyu, vozvrashchayushchuyu celoe". 5.9. Opisatel' typedef Opisaniya, v kotoryh "klass pamyati" specificirovan kak typedef, ne vyzyvayut vydeleniya pamyati. Vmesto etogo oni opredelyayut identifikatory, kotorye pozdnee mozhno ispol'zo- vat' tak, slovno oni yavlyayutsya klyuchevymi slovami, imeyushchimi osnovnye ili proizvodnye tipy. opredelyayushchee_tip_imya: identifikator V predelah oblasti dejstviya opisaniya so specifikatorom typedef kazhdyj identifikator, opisannyj v nem, stanovitsya sintaksicheski ekvivalentnym klyuchevomu slovu, imeyushchemu tot tip, kotoryj associiruet s identifikatorom v opisannom v p. 0.4 smysle. Naprimer, posle opisanij typedef int miles, *klicksp; typedef struct { double re, im;} complex; -33- konstrukcii miles distance; extern klicksp metricp; complex z, *zp; stanovyatsya zakonnymi opisaniyami; pri etom tipom distance yavlyaetsya int, tipom metricp - "ukazatel' na int", tipom z - specificirovannaya struktura i tipom zp - ukazatel' na takuyu strukturu. Specifikator typedef ne vvodit kakih-libo sovershenno novyh tipov, a tol'ko opredelyaet sinonimy dlya tipov, kotorye mozhno bylo by specificirovat' i drugim sposobom. Tak v pri- vedennom vyshe primere peremennaya distance schitaetsya imeyushchej tochno takoj zhe tip, chto i lyuboj drugoj ob容kt, opisannyj v int.  * 6. OPERATORY Za isklyucheniem osobo ogovarivaemyh sluchaev, operatory vypolnyayutsya posledovatel'no. 6.1. Operatornoe vyrazhenie bol'shinstvo operatorov yavlyayutsya operatornymi vyrazheni- yami, kotorye imeyut formu vyrazhenie; Obychno operatornye vyrazheniya yavlyayutsya prisvaivaniyami ili obrashcheniyami k funkciyam. 6.2. Sostavnoj operator (ili blok) S tem, chtoby dopustit' vozmozhnost' ispol'zovaniya nes- kol'kih operatorov tam, gde ozhidaetsya prisutstvie tol'ko odnogo, predusmatrivaetsya sostavnoj operator (kotoryj takzhe nazyvayut "blokom"): sostavnoj operator: {spisok_opisanij spisok_operatorov} neob neob spisok_opisanij: opisanie opisanie spisok_opisanij spisok_operatorov: operator operator spisok_operatorov Esli kakoj-libo identifikator iz spiska_opisanij byl opisan -34- ranee, to vo vremya vypolneniya bloka vneshnee opisanie podav- lyaetsya i snova vstupaet v silu posle vyhoda iz bloka. Lyubaya inicializaciya avtomaticheskih i registrovyh pere- mennyh provoditsya pri kazhdom vhode v blok cherez ego nachalo. V kompilyatore OS DEMOS razreshaetsya (no eto plohaya praktika) peredavat' upravlenie vnutr' bloka; v takom sluchae eti ini- cializacii ne vypolnyayutsya. Inicializacii staticheskih pere- mennyh provodyatsya tol'ko odin raz, kogda nachinaetsya vypolne- nie programmy. Nahodyashchiesya vnutri bloka vneshnie opisaniya ne rezervi- ruyut pamyati, tak chto ih inicializaciya ne razreshaetsya. 6.3. Uslovnye operatory Imeyutsya dve formy uslovnyh operatorov: if (vyrazhenie) operator if (vyrazhenie) operator else operator V oboih sluchayah vychislyaetsya vyrazhenie i, esli ono otlichno ot nulya, to vypolnyaetsya pervyj podoperator. Vo vtorom sluchae, esli vyrazhenie ravno nulyu, vypolnyaetsya vtoroj podoperator. Kak obychno, dvusmyslennost' else razreshaetsya svyazyvaniem else s poslednim vstrechayushchimsya if, u kotorogo net else. 6.4. Operator while Operator while imeet formu while (vyrazhenie) operator Podoperator vypolnyaetsya povtorno do teh por, poka znachenie vyrazheniya ostaetsya otlichnym ot nulya. Proverka proizvoditsya pered kazhdym vypolneniem operatora. 6.5. Operator do Operator do imeet formu do operator while (vyrazhenie) Operator vypolnyaetsya povtorno do teh por, poka znachenie vyrazheniya ne stanet ravnym nulyu. Proverka proizvoditsya posle kazhdogo vypolneniya operatora. 6.6. Operator for Operator for imeet formu (vyrazhenie1;vyrazhenie2;vyrazhenie3)operator neob neob neob -35- Operator for ekvivalenten sleduyushchemu: vyrazhenie1; while (vyrazhenie2) { operator vyrazhenie3; } Takim obrazom, pervoe vyrazhenie opredelyaet inicializaciyu cikla; vtoroe specificiruet proverku, vypolnyaemuyu pered kazh- doj iteraciej, tak chto vyhod iz cikla proishodit togda, kogda znachenie vyrazheniya stanovitsya nulem; tret'e vyrazhenie chasto zadaet prirashchenie parametra, kotoryj vychislyaetsya posle kazhdoj iteracii. Lyuboe vyrazhenie ili vse oni mogut byt' opushcheny. Esli otsutstvuet vtoroe vyrazhenie, to predlozhenie s while schita- etsya ekvivalentnym while(1); drugie otsutstvuyushchie vyrazheniya prosto opuskayutsya iz privedennogo vyshe rasshireniya. 6.7. Operator switch Operator switch (pereklyuchatel'), vyzyvaet peredachu upravleniya k odnomu iz neskol'kih operatorov, v zavisimosti ot znacheniya vyrazheniya. Operator imeet formu switch (vyrazhenie) operator V vyrazhenii provodyatsya obychnye arifmeticheskie preobrazova- niya, rezul'tat dolzhen imet' tip int. Operator obychno yavlya- etsya sostavnym. Lyuboj operator vnutri etogo operatora mozhet byt' pomechen odnim ili bolee variantnym prefiksom case, ime- yushchim formu: case konstantnoe vyrazhenie: Gde konstantnoe vyrazhenie dolzhno imet' tip int. Nikakie dve variantnye konstanty v odnom i tom zhe pereklyuchatele ne mogut imet' odinakovoe znachenie. Tochnoe opredelenie konstantnogo vyrazheniya privoditsya nizhe. Krome togo, mozhet prisutstvovat' odin operatornyj pre- fiks vida default: Pri vypolnenii operatora switch vychislyaetsya vhodyashchee v nego vyrazhenie i sravnivaetsya s kazhdoj variantnoj konstan- toj. Esli odna iz variantnyh konstant okazyvaetsya ravnoj znacheniyu etogo vyrazheniya, to upravlenie peredaetsya opera- toru, kotoryj sleduet za sovpadayushchim variantnym prefiksom. Esli ni odna iz variantnyh