konstant ne sovpadaet so
-36-
znacheniem vyrazheniya i esli pri etom prisutstvuet prefiks
default, to upravlenie peredaetsya operatoru, pomechennomu
etim prefiksom. Esli ni odin iz variantov ne podhodit i pre-
fiks default otsutstvuet, to ni odin iz operatorov v perek-
lyuchatele ne vypolnyaetsya.
Sami po sebe prefiksy case i default ne izmenyayut vypol-
neniya programmy, programma vypolnyaetsya posledovatel'no, poka
ne vstretitsya yavnaya peredacha upravleniya. Dlya vyhoda iz
pereklyuchatelya imeetsya operator break (p.0.8).
Obychno operator, kotoryj vhodit v pereklyuchatel', yavlya-
etsya sostavnym. Opisaniya mogut poyavlyat'sya v nachale etogo
operatora, no inicializacii avtomaticheskih i registrovyh
peremennyh budut neeffektivnymi.
Primer:
switch (regim) {
case 'x': regx++;
case 'X': case 'Y': regY++; break;
case '-': regx = 0; break;
default: err("Oshibka"); goto next;
}
6.8. Operator break
Operator
break;
vyzyvaet zavershenie vypolneniya naimen'shego ohvatyvayushchego
etot operator operatora while, do, for ili switch; upravle-
nie peredaetsya operatoru, sleduyushchemu za zavershennym operato-
rom.
6.9. Operator continue
Operator
continue;
privodit k peredache upravleniya na prodolzhayushchuyu cikl chast'
naimen'shego ohvatyvayushchego etot operator operatora while, do
ili for; to est' na konec cikla. Bolee tochno, v kazhdom iz
operatorov
while(...) { | do { | for(...) {
... | ... | ...
contin: ; | contin: ; | contin: ;
} | } while(...); | }
-37-
operator continue ekvivalenten operatoru goto contin. (Za
contin: sleduet pustoj operator; sm. p. 0.13.).
6.10. Operator vozvrata
Vozvrashchenie iz funkcii v vyzyvayushchuyu programmu osushchestv-
lyaetsya s pomoshch'yu operatora return, kotoryj imeet odnu iz
sleduyushchih form
return;
return vyrazhenie;
V pervom sluchae vozvrashchaemoe znachenie neopredeleno. Vo vto-
rom sluchae v vyzyvayushchuyu funkciyu vozvrashchaetsya znachenie vyra-
zheniya. Esli trebuetsya, vyrazhenie preobrazuetsya k tipu funk-
cii, v kotoroj ono poyavlyaetsya, kak v sluchae prisvaivaniya.
Popadanie na konec funkcii ekvivalentno vozvratu bez vozvra-
shchaemogo znacheniya.
Vozvrashchat' mozhno znachenie arifmeticheskogo tipa, a takzhe
strukturu (no ne massiv).
6.11. Operator goto
Upravlenie mozhno peredavat' bezuslovno s pomoshch'yu opera-
tora
goto identifikator1
Identifikator dolzhen byt' metkoj (p. 0.12), lokalizovannoj v
dannoj funkcii.
6.12. Pomechennyj operator
Pered lyubym operatorom mozhet stoyat' metka, imeyushchaya vid:
identifikator:
Metki ispol'zuyutsya tol'ko dlya ukazaniya mesta, kuda pereda-
etsya upravlenie operatorom goto. Oblast'yu dejstviya metki
yavlyaetsya dannaya funkciya, za isklyucheniem teh podblokov, v
kotoryh tot zhe identifikator opisan snova.
6.13. Pustoj operator
Pustoj operator imeet formu:
;
Pustoj operator okazyvaetsya poleznym, tak kak on pozvolyaet
postavit' metku pered zakryvayushchej skobkoj } sostavnogo ope-
ratora ili ukazat' pustoe telo v operatorah cikla, takih kak
while.
-38-
* 7. VNESHNIE OPREDELENIYA
Si-programma predstavlyaet soboj posledovatel'nost'
vneshnih opredelenij. Vneshnee opredelenie opisyvaet identifi-
kator kak imeyushchij klass pamyati extern (po umolchaniyu), ili,
vozmozhno, static, i specificirovannyj tip. Specifikator tipa
takzhe mozhet byt' pustym; v etom sluchae schitaetsya, chto tip
yavlyaetsya tipom int. Oblast' dejstviya vneshnih opredelenij
rasprostranyaetsya do konca fajla, v kotorom oni privedeny,
tochno tak zhe, kak vliyanie opisanij prostiraetsya do konca
bloka. Sintaksis vneshnih opredelenij ne otlichaetsya ot sin-
taksisa opisanij, za isklyucheniem togo, chto tol'ko na etom
urovne mozhno privodit' tekst funkcij.
7.1. Vneshnee opredelenie funkcii
Opredelenie funkcii imeet formu
opredelenie_funkcii:
specifikatory_opisaniya opisa-
neob
tel'_funkcii telo_funkcii
Edinstvennymi specifikatorami klassa pamyati, dopuskaemymi v
kachestve specifikatorov-opisaniya, yavlyayutsya extern ili
static; o razlichii mezhdu nimi smotri v sleduyushchem razdele.
Opisatel' funkcii podoben opisatelyu dlya funkcii, vozvrashchayu-
shchej ..., za isklyucheniem togo, chto on perechislyaet formal'nye
parametry opredelyaemoj funkcii.
opisatel'_funkcii:
opisatel' (spisok_parametrov)
neob
spisok parametrov:
identifikator
identifikator, spisok_parametrov
Telo_funkcii imeet formu
telo_funkcii:
spisok_opisanij sostavnoj_operator
Identifikatory iz spiska parametrov mogut byt' opisany v
spiske opisanij. Lyuboj identifikator iz etogo spiska, tip
kotorogo ne ukazan, schitaetsya imeyushchim tip int. Edinstvennym
dopustimym zdes' specifikatorom klassa pamyati yavlyaetsya
register; esli takoj klass pamyati specificirovan, to v
nachale vypolneniya funkcii sootvetstvuyushchij fakticheskij para-
metr kopiruetsya, esli eto vozmozhno, v registr.
Vot prostoj primer polnogo opredeleniya funkcii:
-39-
int max(a, b, c)
int a, b, c;
{
int m;
m = (a>b) ? a:b;
return((m>c) ? m:c);
}
Zdes' int - specifikator-tipa, mah(a,b,c) -
opisatel'_funkcii, int a,b,c; - spisok-opisanij formal'nyh
parametrov, { ... } - blok, soderzhashchij tekst operatora.
V yazyke Si vse fakticheskie parametry tipa float preob-
razuyutsya k tipu double, tak chto opisaniya formal'nyh paramet-
rov, ob座avlennyh kak float, mogut rabotat' s parametrami
tipa double. Analogichno, poskol'ku ssylka na massiv v lyubom
kontekste (v chastnosti v fakticheskom parametre) rassmatriva-
etsya kak ukazatel' na pervyj element massiva, opisaniya for-
mal'nyh parametrov vida massiv ... mogut rabotat' s fakti-
cheskimi parametrami tipa ukazatel' na ... I nakonec, pos-
kol'ku funkcii ne mogut byt' peredany funkcii, bessmyslenno
opisyvat' formal'nyj parametr kak funkciyu (ukazateli na
takie ob容kty, konechno, dopuskayutsya).
PRIMECHANIE
V nekotoryh versiyah yazyka Si, v chastnosti, v versiyah
dlya mikroprocessorov, mozhet byt' zapreshchena peredacha
struktur i ob容dinenij cherez parametry funkcii.
7.2. Vneshnie opredeleniya dannyh
Vneshnee opredelenie dannyh imeet formu:
opredelenie_dannyh:
opisanie
Klassom pamyati takih dannyh mozhet byt' extern (v chastnosti,
po umolchaniyu) ili static, no ne auto ili register.
* 8. OBLASTX DEJSTVIYA IDENTIFIKATOROV
Vsya Si-programma ne obyazatel'no kompiliruetsya odnovre-
menno; ishodnyj tekst programmy mozhet hranit'sya v neskol'kih
fajlah i ranee skompilirovannye procedury mogut zagruzhat'sya
iz bibliotek. Svyaz' mezhdu funkciyami mozhet osushchestvlyat'sya kak
cherez yavnye obrashcheniya, tak i v rezul'tate raboty redaktora
svyazej.
Poetomu sleduet rassmotret' dva vida oblastej dejstviya:
vo pervyh, tu, kotoraya mozhet byt' nazvana leksicheskoj
oblast'yu dejstviya identifikatora i kotoraya po sushchestvu
yavlyaetsya toj oblast'yu v programme, gde etot identifikator
-40-
mozhno ispol'zovat', ne vyzyvaya diagnosticheskogo soobshcheniya
"neopredelennyj identifikator"; i vo-vtoryh, oblast' dejst-
viya, kotoraya svyazana s vneshnimi identifikatorami i kotoraya
harakterizuetsya pravilom, chto ssylki na odin i tot zhe vnesh-
nij identifikator yavlyayutsya ssylkami na odin i tot zhe ob容kt.
8.1. Leksicheskaya oblast' dejstviya
Leksicheskaya oblast' dejstviya identifikatorov, opisannyh
vo vneshnih opredeleniyah, prostiraetsya ot opredeleniya do
konca ishodnogo fajla, v kotorom on nahoditsya. Leksicheskaya
oblast' dejstviya identifikatorov, yavlyayushchihsya formal'nymi
parametrami, rasprostranyaetsya na tu funkciyu, k kotoroj oni
otnosyatsya. Leksicheskaya oblast' dejstviya identifikatorov,
opisannyh v nachale bloka, prostiraetsya do konca etogo bloka.
Leksicheskoj oblast'yu dejstviya metok yavlyaetsya ta funkciya, v
kotoroj oni nahodyatsya.
Poskol'ku vse ssylki na odin i tot zhe vneshnij identifi-
kator otnosyatsya k odnomu i tomu zhe ob容ktu, kompilyator pro-
veryaet vse opisaniya odnogo i togo zhe vneshnego identifikatora
na sovmestimost'; v dejstvitel'nosti ih oblast' dejstviya
rasprostranyaetsya na ves' fajl, v kotorom oni nahodyatsya.
Vo vseh sluchayah, odnako, esli nekotoryj identifikator
yavnym obrazom opisan v nachale bloka, vklyuchaya i blok, kotoryj
obrazuet funkciyu, to dejstvie lyubogo opisaniya etogo identi-
fikatora vne bloka priostanavlivaetsya do konca etogo bloka.
Napomnim takzhe, chto identifikatory, sootvetstvuyushchie
obychnym peremennym, s odnoj storony, i identifikatory, soot-
vetstvuyushchie chlenam i yarlykam struktur i ob容dinenij, s dru-
goj storony, formiruyut dva neperesekayushchihsya klassa, kotorye
ne vstupayut v protivorechie. CHleny i yarlyki struktur podchinya-
yutsya tem zhe samym pravilam opredeleniya oblastej dejstviya,
kak i drugie identifikatory. Imena, specificiruemye s
pomoshch'yu typedef, vhodyat v tot zhe klass, chto i obychnye iden-
tifikatory. Oni mogut byt' pereopredeleny vo vnutrennih
blokah, no vo vnutrennem opisanii tip dolzhen byt' ukazan
yavno:
typedef float distance;
...
{
auto int distance;
...
Vo vtorom opisanii specifikator tipa int dolzhen prisutstvo-
vat', tak kak v protivnom sluchae eto opisanie budet prinyato
za opisanie bez opisatelej s tipom distance.
-41-
8.2. Oblast' dejstviya vneshnih identifikatorov
Esli funkciya ssylaetsya na identifikator, opisannyj kak
extern, to gde-to sredi fajlov ili bibliotek, obrazuyushchih
polnuyu programmu, dolzhno soderzhat'sya vneshnee opredelenie
etogo identifikatora. Vse funkcii dannoj programmy, kotorye
ssylayutsya na odin i tot zhe vneshnij identifikator, ssylayutsya
na odin i tot zhe ob容kt, tak chto sleduet pozabotit'sya, chtoby
specificirovannye v etom opredelenii tip i razmer byli sov-
mestimy s tipom i razmerom, ukazyvaemymi v kazhdoj funkcii,
kotoraya ssylaetsya na eti dannye.
Poyavlenie klyuchevogo slova extern vo vneshnem opredelenii
ukazyvaet na to, chto pamyat' dlya opisannyh v nem identifika-
torov budet vydelena v drugom fajle. Sledovatel'no, v sosto-
yashchej iz mnogih fajlov programme vneshnee opredelenie identi-
fikatora, ne soderzhashchee specifikatora extern, dolzhno poyav-
lyat'sya tol'ko v odnom iz etih fajlov. Lyubye drugie fajly,
kotorye zhelayut dat' vneshnee opredelenie etogo identifika-
tora, dolzhny vklyuchat' v eto opredelenie slovo extern. Iden-
tifikator mozhet byt' inicializirovan tol'ko v tom opisanii,
kotoroe privodit k vydeleniyu pamyati.
Iz etogo pravila v OS DEMOS imeetsya isklyuchenie. Vneshnij
ob容kt mozhet prisutstvovat' v neskol'kih opisaniyah bez
extern. Pri etom dlina ob容kta v raznyh opisaniyah dolzhna
sovpadat', a inicializaciya, esli ona est', dolzhna provo-
dit'sya rovno v odnom iz opisanij. Pri narushenii etih pravil
budet vydana oshibka na etape redaktirovanii svyazej prog-
rammy.
Identifikatory, vneshnee opredelenie kotoryh nachinaetsya
so slova static, nedostupny iz drugih fajlov. Funkcii mogut
byt' opisany kak static.
8.3. Neyavnye opisaniya
Ne vsegda neobhodimo specificirovat' i klass pamyati i
tip identifikatora v opisanii. Vo vneshnih opredeleniyah i
opisaniyah formal'nyh parametrov i chlenov struktur klass
pamyati opredelyaetsya po kontekstu. Esli v nahodyashchemsya vnutri
funkcii opisanii ne ukazan tip, a tol'ko klass pamyati, to
predpolagaetsya, chto identifikator imeet tip int; esli ne
ukazan klass pamyati, a tol'ko tip, to identifikator predpo-
lagaetsya opisannym kak auto. Isklyuchenie iz poslednego pra-
vila daetsya dlya funkcij, potomu chto specifikator auto dlya
funkcij yavlyaetsya bessmyslennym (yazyk Si ne v sostoyanii kom-
pilirovat' programmu v stek); esli identifikator imeet tip
funkciya, vozvrashchayushchaya ..., to on predpolagaetsya neyavno opi-
sannym kak extern.
Vhodyashchij v vyrazhenie i neopisannyj ranee identifikator,
za kotorym sleduet skobka (, schitaetsya opisannym po
-42-
kontekstu kak funkciya, vozvrashchayushchaya int.
/* extern */ int tab[100];
static /* int */ t1;
/* int */ func(i) /* int i; */
{ register /* int */ k;
/* auto */ char buf[512];
/* extern int f1(); */
... f1(a,b) ...
* 9. PREPROCESSOR YAZYKA 'SI'
Kompilyator yazyka Si soderzhit preprocessor, kotoryj poz-
volyaet osushchestvlyat' makropodstanovki, uslovnuyu kompilyaciyu i
vklyuchenie imenovannyh fajlov. Stroki, nachinayushchiesya s #,
yavlyayutsya komandami etogo preprocessora. Sintaksis etih strok
ne svyazan s ostal'nym yazykom; oni mogut poyavlyat'sya v lyubom
meste i ih vliyanie rasprostranyaetsya (nezavisimo ot oblasti
dejstviya) do konca ishodnogo programmnogo fajla. Fakticheski
preprocessor rasshiryaet vozmozhnosti yazyka Si, realizuya takie
funkcii, kotorye v drugih yazykah vhodyat v sostav samogo
yazyka (naprimer, parametricheskie konstanty v Fortrane-77).
9.1. Zamena leksem
Komanda
#define identifikator stroka_leksem
(obratite vnimanie na otsutstvie v konce tochki s zapyatoj)
privodit k tomu, chto preprocessor zamenyaet posleduyushchie vhozh-
deniya etogo identifikatora na ukazannuyu stroku leksem.
Stroka vida
#define identifikator(identifika-
tor,...,identifikator) stroka_leksem
gde mezhdu pervym identifikatorom i otkryvayushchejsya skobkoj "("
net probela, predstavlyaet soboj makroopredelenie s argumen-
tami. V dal'nejshem pervyj identifikator, za kotorym sleduet
otkryvayushchaya skobka "(", posledovatel'nost' razdelennyh zapya-
tymi leksem i zakryvayushchaya skobka ")", zamenyayutsya strokoj
leksem iz opredeleniya. Kazhdoe vhozhdenie identifikatora, upo-
myanutogo v spiske formal'nyh parametrov v opredelenii, zame-
nyaetsya sootvetstvuyushchej strokoj leksem iz obrashcheniya. Fakti-
cheskimi argumentami v obrashchenii yavlyayutsya stroki leksem, raz-
delennye zapyatymi; odnako zapyatye, vhodyashchie v zakavychennye
stroki ili zaklyuchennye v kruglye skobki, ne razdelyayut argu-
mentov. Kolichestvo formal'nyh i fakticheskih parametrov
dolzhno sovpadat'. Tekst vnutri stroki ili simvol'noj kons-
tanty ne podlezhit zamene.
-43-
V oboih sluchayah zamenennaya stroka prosmatrivaetsya snova
s cel'yu obnaruzheniya drugih identifikatorov, izvestnyh prep-
rocessoru. V oboih sluchayah slishkom dlinnaya stroka opredele-
niya mozhet byt' prodolzhena na drugoj stroke, esli pomestit' v
konce prodolzhaemoj stroki obratnuyu kosuyu chertu "\".
Opisyvaemaya vozmozhnost' osobenno polezna dlya opredele-
niya "ob座avlyaemyh konstant", kak, naprimer,
#define TABSIZE 100
int table[TABSIZE];
ili dlya zameny nekotoryh funkcij s pomoshch'yu makropodstanovki:
#define max(a,b) ((a)>(b)?(a):(b))
x = max(y,20)
(v poslednem opredelenii a i b vzyaty v skobki, dlya togo,
chtoby fakticheskimi parametrami makro mogli by byt' proiz-
vol'nye vyrazheniya.
Komanda
#undef identifikator
privodit k otmene preprocessornogo opredeleniya dannogo iden-
tifikatora.
Opredelit' identifikator mozhno ne tol'ko s pomoshch'yu
komandy #define, no takzhe i pri vyzove kompilyatora, s
pomoshch'yu parametrov komandy cc.
9.2. Vklyuchenie fajlov
Komanda
#include "filename"
privodit k zamene etoj stroki na vse soderzhimoe fajla s ime-
nem filename. Fajl s etim imenem snachala ishchetsya v tekushchem
spravochnike, a zatem v drugih "standartnyh" mestah, oprede-
lyaemyh pol'zovatelem pri vyzove kompilyatora. V otlichie ot
etogo komanda
#include <filename>
ishchet fajl tol'ko v standartnom spravochnike sistemy.
V OS DEMOS fajl ishchetsya v spravochnike /usr/include.
Komandy #include mogut byt' vlozhennymi.
-44-
9.3. Uslovnaya kompilyaciya
Komanda preprocessora
#if konstantnoe vyrazhenie
proveryaet, otlichno li ot nulya znachenie konstantnogo vyrazhe-
niya. Komanda:
#ifdef identifikator
proveryaet, opredelen li etot identifikator v nastoyashchij
moment v preprocessore, t.e. opredelen li etot identifikator
s pomoshch'yu komandy #define. Komanda:
#ifndef identifikator
proveryaet, yavlyaetsya li etot identifikator v dannyj moment ne
opredelennym dlya preprocessora.
Za kazhdym iz treh perechislennyh vidov strok mozhet sle-
dovat' proizvol'noe chislo strok, vozmozhno soderzhashchih komandu
preprocessora
#else
a zatem dolzhna sledovat' komanda:
#endif
Esli proveryaemoe uslovie istinno, to lyubye stroki mezhdu
#else i #endif ignoriruyutsya. Esli proveryaemoe uslovie lozhno,
to lyubye stroki mezhdu proveryaemoj strokoj i #else ili, pri
otsutstvii #else, #endif ignoriruyutsya.
|ti konstrukcii mogut byt' vlozhennymi.
Naprimer:
#ifdef DEBUG
fprintf(stderr,"i=%o j=%d\n",i,j);
#endif
Peremennaya preprocessora mozhet byt' opredelena ne tol'ko v
samoj programme, no i pri vyzove translyatora.
9.4. Komanda #line
Dlya drugih preprocessorov, generiruyushchih Si-programmy,
polezna sleduyushchaya komanda:
#line konstanta "imya_fajla"
-45-
kotoraya soobshchaet kompilyatoru (dlya diagnosticheskih soobshche-
nij), chto sleduyushchaya stroka ishodnogo fajla imeet nomer,
zadavaemyj konstantoj, i chto tekushchij vhodnoj fajl imenuetsya
imenem_fajla. Esli imya_fajla otsutstvuet, to zapominaemoe
imya fajla ne izmenyaetsya. Primer:
#line 250 "gram.y"
* 10. DOPOLNITELXNAYA INFORMACIYA O TIPAH
V etom razdele obobshchayutsya svedeniya ob operaciyah, koto-
rye mozhno primenyat' tol'ko k ob容ktam opredelennyh tipov.
10.1. Struktury i ob容dineniya
So strukturami i ob容dineniyami mogut proizvodit'sya sle-
duyushchie operacii: ssylka na odin iz chlenov struktury ili
ob容dineniya (s pomoshch'yu operacii .), poluchenie adresa (s
pomoshch'yu unarnoj operacii &), prisvaivanie struktury struk-
ture, peredacha struktury v kachestve formal'nogo parametra,
vozvrat struktury funkciej. Vse ostal'nye operacii zapre-
shcheny.
V realizacii vozvrashcheniya struktur funkciyami na CM-|VM
imeetsya kovarnyj defekt: esli vo vremya vozvrata proishodit
preryvanie i ta zhe samaya funkciya reenterabel'no vyzyvaetsya
vo vremya etogo preryvaniya, to znachenie, vozvrashchaemoe iz per-
vogo vyzova, mozhet byt' isporcheno. |ta trudnost' mozhet voz-
niknut' tol'ko pri nalichii istinnogo preryvaniya, kak iz ope-
racionnoj sistemy, tak i iz programmy pol'zovatelya; preryva-
niya, kotoroe dejstvitel'no asinhronno; obychnye rekursivnye
vyzovy sovershenno bezopasny.
V razdele "Vyrazheniya" govoritsya, chto pri pryamoj ili
kosvennoj ssylke na strukturu (s pomoshch'yu . ili ->) imya
sprava dolzhno byt' chlenom konstrukcii, nazvannoj ili ukazan-
noj vyrazheniem sleva. |to ogranichenie ne navyazyvaetsya strogo
kompilyatorom, chtoby dat' vozmozhnost' obojti pravila soot-
vetstviya tipov. V dejstvitel'nosti pered . dopuskaetsya
lyuboe l_znachenie i zatem predpolagaetsya, chto eto l_znachenie
imeet formu struktury, dlya kotoroj stoyashchee sprava imya yavlya-
etsya chlenom. Takim zhe obrazom, ot vyrazheniya, stoyashchego pered
->, trebuetsya tol'ko byt' ukazatelem ili celym. V sluchae
ukazatelya predpolagaetsya, chto on ukazyvaet na strukturu, dlya
kotoroj stoyashchee sprava imya yavlyaetsya chlenom. V sluchae celogo
ono rassmatrivaetsya kak absolyutnyj adres sootvetstvuyushchej
struktury, zadannyj v edinicah mashinnoj pamyati.
Takie struktury ne yavlyayutsya perenosimymi.
-46-
10.2. Funkcii
Tol'ko dve operacii mozhno primenyat' k funkcii: vyzvat'
ee ili izvlech' ee adres. Esli imya funkcii vhodit v vyrazhenie
ne v pozicii imeni funkcii, sootvetstvuyushchej obrashcheniyu k nej,
to generiruetsya ukazatel' na etu funkciyu. Sledovatel'no,
chtoby peredat' odnu funkciyu drugoj, mozhno napisat'
int f();
...
g(f);
togda opredelenie funkcii g moglo by vyglyadet' tak:
g(funcp)
int (*funcp)();
{
...
(*funcp)();
...
}
Obratite vnimanie, chto v vyzyvayushchej procedure funkciya f
dolzhna byt' opisana yavno, potomu chto za ee poyavleniem v g(f)
ne sleduet skobka "(".
10.3. Massivy, ukazateli i indeksaciya
Kazhdyj raz, kogda identifikator, imeyushchij tip massiva,
poyavlyaetsya v vyrazhenii, on preobrazuetsya v ukazatel' na per-
vyj chlen etogo massiva. Iz-za etogo preobrazovaniya massivy
ne yavlyayutsya l_znacheniyami. Po opredeleniyu operaciya indeksacii
"[]" interpretiruetsya takim obrazom, chto e1[e2] schitaetsya
identichnym vyrazheniyu *((e1)+(e2)). Soglasno pravilam preob-
razovanij, primenyaemym pri operacii +, esli e1 - massiv, a
e2 - celoe, to e1[e2] ssylaetsya na e2-j chlen massiva e1.
Poetomu, nesmotrya na nesimmetrichnyj vid, operaciya indeksacii
yavlyaetsya kommutativnoj.
V sluchae mnogomernyh massivov primenyaetsya analogichnoe
pravilo. Esli e yavlyaetsya n-mernym massivom razmera
i*j*...*k, to pri poyavlenii v vyrazhenii e preobrazuetsya v
ukazatel' na (n-1)-mernyj massiv razmera j*...*k. Esli ope-
raciya * libo yavno, libo neyavno, kak rezul'tat indeksacii,
primenyaetsya k etomu ukazatelyu, to rezul'tatom operacii budet
ukazannyj (n-1)-mernyj massiv, kotoryj sam nemedlenno preob-
razuetsya v ukazatel'.
Rassmotrim, naprimer, opisanie:
int u[3][5];
Zdes' u - massiv celyh razmera 3*5. Pri poyavlenii v
-47-
vyrazhenii u preobrazuetsya v ukazatel' na pervyj iz treh mas-
sivov iz 5 celyh. V vyrazhenii u[i], kotoroe ekvivalentno
*(u+i), snachala u preobrazuetsya v ukazatel' tak, kak opisano
vyshe; zatem i preobrazuetsya k tipu u, chto vyzyvaet umnozhenie
i na dlinu ob容kta, na kotoryj ukazyvaet ukazatel', a imenno
na 5 celyh ob容ktov. Rezul'taty skladyvayutsya, i primenenie
kosvennoj adresacii daet massiv (iz 5 celyh), kotoryj v svoyu
ochered' preobrazuetsya v ukazatel' na pervoe iz etih celyh.
Esli v vyrazhenie vhodit i drugoj indeks, to ta zhe samaya
argumentaciya primenyaetsya snova; rezul'tatom na etot raz
budet celoe.
Iz vsego etogo sleduet, chto massivy v yazyke Si hranyatsya
postrochno (poslednij indeks izmenyaetsya bystree vsego) i chto
pervyj indeks v opisanii pomogaet opredelit' obshchee koli-
chestvo pamyati, trebuemoe dlya hraneniya massiva, no ne igraet
nikakoj drugoj roli v vychisleniyah, svyazannyh s indeksaciej.
10.4. YAvnye preobrazovaniya ukazatelej
Razreshayutsya opredelennye preobrazovaniya s ispol'zova-
niem ukazatelej. Oni imeyut nekotorye zavisyashchie ot konkret-
noj realizacii aspekty. Vse eti preobrazovaniya zadayutsya s
pomoshch'yu operacii yavnogo preobrazovaniya tipa.
Ukazatel' mozhet byt' preobrazovan v lyuboj iz celochis-
lennyh tipov, dostatochno bol'shoj dlya ego hraneniya. Trebuetsya
li pri etom int ili long, zavisit ot konkretnoj mashiny (v OS
DEMOS dlya SM |VM trebuetsya int). Preobrazuyushchaya funkciya
takzhe yavlyaetsya mashinno-zavisimoj, no ona budet vpolne
estestvennoj dlya teh, kto znaet strukturu adresacii v
mashine. Detali dlya nekotoryh konkretnyh mashin privodyatsya
nizhe.
Ob容kt celochislennogo tipa mozhet byt' yavnym obrazom
preobrazovan v ukazatel'. Takoe preobrazovanie vsegda pere-
vodit preobrazovannoe iz ukazatelya celoe v tot zhe samyj uka-
zatel', no v drugih sluchayah ono budet mashinno-zavisimym.
Ukazatel' na odin tip mozhet byt' preobrazovan v ukaza-
tel' na drugoj tip. Esli preobrazuemyj ukazatel' ne ukazy-
vaet na ob容kty, kotorye podhodyashchim obrazom vyravneny v
pamyati, to rezul'tiruyushchij ukazatel' mozhet pri ispol'zovanii
vyzyvat' oshibki adresacii. Garantiruetsya, chto ukazatel' na
ob容kt zadannogo razmera mozhet byt' preobrazovan v ukazatel'
na ob容kt men'shego razmera i snova obratno, ne preterpev pri
etom izmeneniya.
Naprimer, procedura raspredeleniya pamyati alloc mogla by
prinimat' zapros na razmer vydelyaemogo ob容kta v bajtah, a
vozvrashchat' ukazatel' na simvoly; eto mozhno bylo by ispol'zo-
vat' sleduyushchim obrazom.
-48-
extern char *alloc();
double *dp;
dp=(double*) alloc(sizeof(double));
*dp=22.0/7.0;
Funkciya alloc dolzhna obespechivat' (mashinno-zavisimym sposo-
bom), chto vozvrashchaemoe eyu znachenie budet podhodyashchim dlya pre-
obrazovaniya v ukazatel' na double; v takom sluchae ispol'zo-
vanie etoj funkcii budet perenosimym.
Predstavlenie ukazatelya na CM-|VM sootvetstvuet 16-
bitovomu celomu i izmeryaetsya v bajtah. Ob容kty tipa char ne
imeyut nikakih ogranichenij na vyravnivanie; vse ostal'nye
ob容kty dolzhny imet' chetnye adresa.
* 11. KONSTANTNYE VYRAZHENIYA
V neskol'kih mestah v yazyke Si trebuyutsya vyrazheniya,
kotorye posle vychisleniya stanovyatsya konstantami: posle vari-
antnogo prefiksa case, v kachestve granic massivov i v inici-
alizatorah. V pervyh dvuh sluchayah vyrazhenie mozhet soderzhat'
tol'ko celye konstanty, simvol'nye konstanty i vyrazheniya
sizeof, vozmozhno svyazannye libo binarnymi operaciyami
+ - * / . % & | ^ << >> == 1= <> <= >=
libo unarnymi operaciyami
- ~
libo ternarnoj operaciej
?:
Kruglye skobki mogut ispol'zovat'sya dlya gruppirovki, no ne
dlya obrashcheniya k funkciyam.
V sluchae inicializatorov dopuskaetsya bol'shaya (udarenie
na bukvu o) svoboda; krome perechislennyh vyshe konstantnyh
vyrazhenij mozhno takzhe primenyat' unarnuyu operaciyu & k vneshnim
ili staticheskim ob容ktam i k vneshnim ili staticheskim massi-
vam, imeyushchim v kachestve indeksov konstantnoe vyrazhenie.
Unarnaya operaciya & mozhet byt' takzhe primenena neyavno, v
rezul'tate poyavleniya neindeksirovannyh massivov i funkcij.
Osnovnoe pravilo zaklyuchaetsya v tom, chto posle vychisleniya
inicializator dolzhen stanovitsya libo konstantoj, libo adre-
som ranee opisannogo vneshnego ili staticheskogo ob容kta plyus
ili minus konstanta.
* 12. SOOBRAZHENIYA O PERENOSIMOSTI
Odnim iz dostoinstv yazyka Si schitaetsya perenosimost'
programm na Si, kotoraya svyazana kak s otnositel'noj mashinnoj
-49-
nezavisimost'yu samogo yazyka, tak i s sovmestimost'yu sredy,
obespechivaemoj sovmestimymi s OS UNIX operacionnymi siste-
mami. Vmeste s tem, pri napisanii na yazyke Si takih prog-
ramm, kotorye ne dolzhny zaviset' ot konkretnoj |VM, neobho-
dimo uchityvat' to, chto nekotorye chasti yazyka Si po svoej
suti mashinno-zavisimy. Sleduyushchee nizhe perechislenie potenci-
al'nyh trudnostej hotya i ne yavlyayutsya vseob容mlyushchimi, no
vydelyaet osnovnye iz nih.
Voprosy, celikom svyazannye s apparatnym oborudovaniem,
takie kak razmer slova, svojstva veshchestvennoj arifmetiki i
celogo deleniya, ne predstavlyayut osobennyh zatrudnenij. Dru-
gie aspekty apparatnyh sredstv nahodyat svoe otrazhenie v raz-
lichnyh realizaciyah. Nekotorye iz nih, v chastnosti, znakovoe
rasshirenie (preobrazuyushchee otricatel'nyj simvol v otricatel'-
noe celoe) i poryadok, v kotorom pomeshchayutsya bajty v slove,
predstavlyayut soboj nepriyatnost', kotoraya dolzhna tshchatel'no
otslezhivat'sya. Bol'shinstvo ostal'nyh problem etogo tipa ne
vyzyvaet skol'ko_nibud' znachitel'nyh zatrudnenij.
CHislo peremennyh tipa register, kotoroe fakticheski
mozhet byt' pomeshcheno v registry, menyaetsya ot mashiny k mashine,
takzhe kak i nabor dopustimyh dlya nih tipov. Tem ne menee vse
kompilyatory na svoih mashinah rabotayut nadlezhashchim obrazom;
lishnie ili nedopustimye registrovye opisaniya ignoriruyutsya.
Nekotorye trudnosti voznikayut tol'ko pri ispol'zovanii
somnitel'noj praktiki programmirovaniya, ili pri ispol'zova-
nii osobennostej konkretnoj realizacii. Pisat' programmy,
kotorye zavisyat ot takih osobennostej, chrezvychajno nera-
zumno.
YAzykom ne ukazyvaetsya poryadok vychisleniya argumentov
funkcij; oni vychislyayutsya sprava nalevo na CM-|VM i |VM PDP-
11 i VAXR-11 firmy DEC i sleva napravo na bol'shinstve
ostal'nyh mashin. Poryadok, v kotorom proishodyat pobochnye
effekty, takzhe ne specificiruetsya.
Tak kak simvol'nye konstanty v dejstvitel'nosti yavlya-
yutsya ob容ktami tipa int, dopuskaetsya ispol'zovanie simvol'-
nyh konstant, sostoyashchih iz neskol'kih simvolov. Odnako, pos-
kol'ku poryadok, v kotorom simvoly pripisyvayutsya k slovu,
menyaetsya ot mashiny k mashine, konkretnaya realizaciya okazyva-
etsya ves'ma mashinno_zavisimoj.
Poryadok prisvaivaniya polej k slovam i simvolov k celym
takzhe zavisit ot |VM. Takie razlichiya nezametny dlya izoliro-
vannyh programm, v kotoryh ne razresheno smeshivat' tipy (pre-
obrazuya, naprimer, ukazatel' na int v ukazatel' na char i
zatem proveryaya ukazyvaemuyu pamyat'), no dolzhny uchityvat'sya
pri soglasovanii s nakladyvaemymi izvne shemami pamyati.
-50-
YAzyk, prinyatyj na razlichnyh kompilyatorah, otlichaetsya
tol'ko neznachitel'nymi detalyami. Samoe zametnoe otlichie sos-
toit v tom, chto ispol'zuemyj v nastoyashchee vremya kompilyator na
CM-|VM ne inicializiruet struktury, kotorye soderzhat polya
bitov, ne imeet tipa "unsigned char" i imeet nekotorye ogra-
nicheniya na operacii prisvaivaniya v opredelennyh kontekstah,
svyazannyh s ispol'zovaniem znacheniya prisvaivaniya struktur.
12.1. Anahronizmy
V staryh programmah mozhno vstretit' nekotorye ustarev-
shie konstrukcii. Hotya bol'shinstvo versij kompilyatora podder-
zhivaet takie anahronizmy, oni v konce koncov ischeznut, osta-
viv za soboj tol'ko problemy perenosimosti.
V rannih versiyah Si dlya problem prisvaivaniya ispol'zo-
valas' forma =op, a ne op=, privodya k dvusmyslennostyam,
tipichnym primerom kotoryh yavlyaetsya
h =-1
gde h fakticheski umen'shaetsya, poskol'ku operacii = i - pri-
mykayut drug k drugu, no chto vpolne moglo rassmatrivat'sya i
kak prisvaivanie -1 k h.
Sintaksis inicializatorov izmenilsya: ran'she znak
ravenstva, s kotorogo nachinaetsya inicializator, otsutstvo-
val, tak chto vmesto
int h = 1;
ispol'zovalos'
int h 1;
izmenenie bylo vneseno iz_za inicializacii
int f (1+2)
kotoraya dostatochno sil'no napominaet opredelenie funkcii,
chtoby smutit' kompilyatory.
* 13. STANDARTNAYA BIBLIOTEKA VVODA I VYVODA
Sredstva vvoda/vyvoda ne yavlyayutsya sostavnoj chast'yu
yazyka Si. V etoj glave budet opisana "standartnaya biblio-
teka vvoda/vyvoda", to est' nabor funkcij, razrabotannyh dlya
obespecheniya standartnoj sistemy vvoda/vyvoda dlya Si- prog-
ramm. |ti funkcii otrazhayut tol'ko te operacii, kotorye mogut
byt' obespecheny na bol'shinstve sovremennyh operacionnyh sis-
tem. Procedury dostatochno effektivny dlya togo, chtoby pol'zo-
vateli redko chuvstvovali neobhodimost' obojti ih "radi
-51-
effektivnosti", kak by ni byla vazhna konkretnaya zadacha. I
nakonec, eti procedury byli zadumany avtorami yazyka "pereno-
simymi" v tom smysle, chto oni dolzhny sushchestvovat' v sovmes-
timom vide na lyuboj sisteme, gde imeetsya yazyk Si, i chto
programmy, kotorye ogranichivayut svoi vzaimodejstviya s sis-
temnymi vozmozhnostyami, predostavlyaemymi standartnoj biblio-
tekoj, mozhno budet perenosit' s odnoj sistemy na druguyu po
sushchestvu bez izmenenij.
Dalee opisyvayutsya osnovnye principy organizacii
vvoda/vyvoda v programmah na yazyke Si, ispol'zuyushchih biblio-
teku vvoda/vyvoda. Polnoe opisanie etoj biblioteki imeetsya v
rukovodstve programmista (chast' 4) ili v operativnoj doku-
mentacii ("man(3)"). Programmy, rabotayushchie v OS DEMOS,
mogut takzhe obrashchat'sya k funkciyam vvoda/vyvoda nizkogo
urovnya, kotorye realizovany neposredstvenno v yadre OS DEMOS,
no takaya neobhodimost' voznikaet dostatochno redko.
13.1. Obrashchenie k standartnoj biblioteke
Kazhdyj ishodnyj fajl, kotoryj obrashchaetsya k funkcii iz
standartnoj biblioteki, dolzhen gde to v nachale soderzhat'
stroku
#include <stdio.h>
V fajle stdio.h opredelyayutsya nekotorye makrosy i peremennye,
ispol'zuemye bibliotekoj vvoda/vyvoda.
13.2. Standartnyj vvod i vyvod
Samyj prostoj mehanizm vvoda zaklyuchaetsya v chtenii po
odnomu simvolu za raz iz "standartnogo vvoda" (obychno s ter-
minala pol'zovatelya) s pomoshch'yu funkcii getchar. Funkciya
getchar() celogo tipa pri kazhdom k nej obrashchenii vozvrashchaet
sleduyushchij vvodimyj simvol. V bol'shinstve sistem, kotorye
podderzhivayut yazyk Si, terminal mozhet byt' zamenen nekotorym
fajlom s pomoshch'yu oboznacheniya "<". Esli nekotoraya programma
prog ispol'zuet funkciyu getchar, to komandnaya stroka
prog <infile
privedet k tomu, chto prog budet chitat' iz fajla infile, a ne
s terminala. Pereklyuchenie vvoda delaetsya takim obrazom, chto
sama programma prog ne zamechaet izmeneniya; v chastnosti
stroka "<infile" ne vklyuchaetsya v komandnuyu stroku argumentov
(sm. sleduyushchuyu glavu). Pereklyuchenie vvoda okazyvaetsya neza-
metnym i v tom sluchae, kogda vyvod postupaet iz drugoj prog-
rammy cherez mezhprocessnyj kanal. Naprimer, komandnaya stroka
otherprog | prog
progonyaet dve programmy, otherprog i prog, tak, chto
-52-
standartnym vvodom dlya prog sluzhit standartnyj vyvod other-
prog.
Funkciya getchar vozvrashchaet znachenie EOF, kogda dostiga-
etsya konec fajla, kakoj by vvod ona pri etom ne schityvala.
Standartnaya biblioteka polagaet simvolicheskuyu konstantu EOF
ravnoj -1 (posredstvom #define v fajle stdio.h), no proverki
sleduet pisat' v terminah EOF, a ne -1, chtoby izbezhat' zavi-
simosti ot konkretnogo znacheniya.
Vyvod mozhno osushchestvlyat' s pomoshch'yu funkcii putchar(c),
pomeshchayushchej simvol 'c' v "standartnyj vyvod", kotoryj po
umolchaniyu yavlyaetsya terminalom. Vyvod mozhno pri vyzove prog-
rammy napravit' v nekotoryj fajl s pomoshch'yu oboznacheniya ">".
Esli prog ispol'zuet putchar, to komandnaya stroka
prog > outfile
privedet k zapisi standartnogo vyvoda v fajl outfile, a ne
na terminal. V sisteme DEMOS mozhno takzhe ispol'zovat' mezhp-
rocessnyj kanal.
V standartnoj biblioteke vvoda/vyvoda "funkcii" getchar
i putchar na samom dele mogut byt' makrosami. |to pozvolyaet
izbezhat' nakladnyh rashodov na obrashchenie k funkcii dlya obra-
botki kazhdogo simvola.
13.3. Formatnyj vyvod - funkciya printf
Dve funkcii: printf dlya vyvoda i scanf dlya vvoda (sle-
duyushchij razdel) pozvolyayut preobrazovyvat' chislennye velichiny
v simvol'noe predstavlenie i obratno. Oni takzhe pozvolyayut
generirovat' i interpretirovat' formatnye stroki. Funkciya
printf(control, arg1, arg2, ...)
preobrazuet argumenty v tekstovuyu formu v sootvetstvii s
formatami, zadannymi v upravlyayushchej stroke control, i vydaet
rezul'tat v standartnyj vyvod. Upravlyayushchaya stroka soderzhit
dva tipa ob容ktov: obychnye simvoly, kotorye prosto kopiru-
yutsya v vyhodnoj potok, i specifikacii preobrazovanij, kazhdaya
iz kotoryh vyzyvaet preobrazovanie i pechat' ocherednogo argu-
menta printf.
Kazhdaya specifikaciya preobrazovaniya nachinaetsya s simvola
"%" i zakanchivaetsya simvolom preobrazovaniya (bukvoj, oprede-
lyayushchej tip preobrazovaniya). Mezhdu "%" i simvolom preobrazo-
vaniya mogut nahodit'sya:
- Znak minus, kotoryj vyzyvaet vyravnivanie preobrazo-
vannogo argumenta po levomu krayu polya.
-53-
- Stroka cifr, zadayushchaya minimal'nuyu shirinu polya. Preob-
razovannoe chislo budet napechatano v pole po krajnej
mere etoj shiriny, a esli neobhodimo, to i v bolee
shirokom. Esli preobrazovannyj argument imeet men'she
simvolov, chem ukazannaya shirina polya, to on budet
dopolnen sleva (ili sprava, esli bylo ukazano vyrav-
nivanie po levomu krayu) zapolnyayushchimi simvolami do
etoj shiriny. Zapolnyayushchim simvolom obychno yavlyaetsya
probel, a esli shirina polya ukazyvaetsya s lidiruyushchim
nulem, to etim simvolom budet nul' (lidiruyushchij nul' v
dannom sluchae ne oznachaet vos'merichnoj shiriny polya).
- Tochka, kotoraya otdelyaet shirinu polya ot sleduyushchej
stroki cifr.
- Stroka cifr (tochnost'); ukazyvaet maksimal'noe chislo
simvolov stroki, kotorye dolzhny byt' napechatany, ili
chislo pechataemyh sprava ot desyatichnoj tochki cifr dlya
peremennyh tipa float ili double.
- Modifikator dliny l, kotoryj ukazyvaet, chto soot-
vetstvuyushchij element dannyh imeet tip long, a ne int.
Nizhe privodyatsya simvoly preobrazovaniya i ih smysl:
d - argument preobrazuetsya k desyatichnomu vidu;
o - argument preobrazuetsya v bezznakovuyu vos'merichnuyu
formu (bez lidiruyushchego nulya);
x - argument preobrazuetsya v bezznakovuyu shestnadcaterich-
nuyu formu (bez lidiruyushchih 0h);
u - argument preobrazuetsya v bezznakovuyu desyatichnuyu
formu;
c - argument rassmatrivaetsya kak otdel'nyj simvol;
s - argument yavlyaetsya strokoj: simvoly stroki pechatayutsya
do teh por, poka ne budet dostignut nulevoj simvol
ili ne budet napechatano kolichestvo simvolov, ukazan-
noe v specifikacii tochnosti;
e - argument, rassmatrivaemyj kak peremennaya tipa float
ili double, preobrazuetsya v desyatichnuyu formu v vide
[-]m.nnnnnne[+-]hh, gde dlina stroki iz n opredelya-
etsya ukazannoj tochnost'yu. Tochnost' po umolchaniyu ravna
6;
f - argument, rassmatrivaemyj kak peremennaya tipa float
ili double, preobrazuetsya v desyatichnuyu formu v vide
[-]mmm.nnnnn, gde dlina stroki iz n opredelyaetsya uka-
zannoj tochnost'yu. Tochnost' po umolchaniyu ravna 6.
-54-
Otmetim, chto eta tochnost' ne opredelyaet kolichestvo
pechataemyh v formate f znachashchih cifr;
g - ispol'zuetsya ili format %e ili %f, kakoj koroche; nez-
nachashchie nuli ne pechatayutsya.
Vmesto "ld"mozhno ispol'zovat' "D", vmesto "lo" - "O", vmesto
"lx" - "X".
Esli idushchij za % simvol ne yavlyaetsya simvolom preobrazo-
vaniya, to pechataetsya sam etot simvol; sledovatel'no,simvol %
mozhno napechatat', ukazav %%.
Bol'shinstvo iz formatnyh preobrazovanij ochevidno.
Edinstvennym isklyucheniem yavlyaetsya to, kak tochnost' vzaimo-
dejstvuet so strokami. Sleduyushchaya tablica demonstriruet vliya-
nie razlichnyh specifikacij na pechat' "hello, world" (12 sim-
volov). Vokrug kazhdogo polya pomeshcheny dvoetochiya dlya togo,
chtoby mozhno bylo opredelit' ego protyazhennost'.
:%10s: :hello, world:
:%10-s: :hello, world:
:%20s: : hello,