sya odni i te zhe uka-
zateli pozicii chteniya/zapisi. Esli novomu processu trebu-
etsya peredat' kakie to otkrytye fajly, ili izmenit' fajly
standartnogo vvoda/vyvoda, nastrojka programmy na eti fajly
delaetsya posle vyzova fork v processe-syne do vyzova execl.
Sleduet zametit', chto pri buferizovannom vvode/vyvode neob-
hodimo sbrosit' bufera pered vyzovom fork(), inache vyvod
nakoplennoj informacii mozhet proizojti dvazhdy - i v
-72-
"roditel'skom", i v novom processe.
15.2.4. Kanal mezhprocessnoj svyazi
Mezhprocessnyj kanal - eto osobyj fajl, ustroennyj takim
obrazom, chto odin process neogranichenno zapisyvaet v nego
informaciyu, a drugoj chitaet, prichem sistema obespechivaet
buferizaciyu dannyh i sinhronizaciyu processov. Mezhprocess-
nye kanaly mogut sozdavat'sya interpretatorom komand shell
ili cshell, naprimer:
ls | pr
Sushchestvuyut bibliotechnye funkcii popen i pclose, pozvolyayushchie
zapustit' parallel'nyj process, kotoryj budet chitat' infor-
maciyu, zapisyvaemuyu v ukazannyj fajl dannym processom, ili,
naprotiv, budet postavlyat' porodivshemu ego processu dannye
dlya chteniya (sm. popen(3)). |ti funkcii ispol'zuyut bazovye
vozmozhnosti postroeniya kanalov, kotorye podderzhivayutsya ope-
racionnoj sistemoj.
Dlya sozdaniya kanala mezhprocessnoj svyazi sluzhit funkciya
pipe:
int fd[2];
...
stat = pipe(fd);
if(stat == -1) /* Byla oshibka */...
Zdes' fd - massiv, v kotoryj zasylaetsya dva deskriptora faj-
lov - fd[1] dlya zapisi v kanal, fd[0] dlya chteniya iz kanala.
|ti deskriptory mogut ispol'zovat'sya naravne s deskriptorami
obychnyh fajlov.
Sinhronizaciya obmenov postroena takim obrazom, chto,
esli process chitaet pustoj kanal, on budet zhdat' poyavleniya
dannyh; esli v kanale ostalos' mnogo neschitannoj informacii,
zapisyvayushchij process budet zhdat' osvobozhdeniya mesta v
kanale. Nakonec, esli u kanala storona dlya zapisi zakryta,
pri chtenii budet poluchen kod otveta "0" - konec fajla.
Kak pravilo, programma sozdaet kanal po zaprosu pipe,
posle chego razdelyaetsya na dve kopii s pomoshch'yu funkcii fork.
Zatem v odnom iz poluchivshihsya processov zakryvaetsya storona
kanala dlya chteniya, v drugom - zakryvaetsya deskriptor zapisi
v kanal. Teper' posle vyzova execl nachinaetsya obmen infor-
maciej po mezhprocessnomu kanalu mezhdu parallel'no vypolnyayu-
shchimisya programmami.
V sluchae, esli obmen dolzhen proishodit' cherez standart-
nyj vvod ili vyvod, ispol'zuetsya funkciya dup dlya svyazyvaniya
deskriptorov fajlov. Naprimer, sleduyushchij fragment programmy
sluzhit dlya zapuska programmy pr tak, chtoby dannye na
-73-
standartnyj vvod programmy pr postupali iz standartnogo
vyvoda osnovnoj programmy:
int fd[2];
#define R 0
#define W 1
pipe(fd);
if(fork() == 0)
{ close(fd[W]); close(0); dup(fd[R]);
close(fd[R]);
execl("/bin/pr","pr",NULL);
exit(1); /* Esli oshibka v execl */
}
close(fd[R]); close(1); dup(fd[W]);
close(fd[W]);
.... schet, pri zapisi proveryaem, ne bylo
.... li oshibki zapisi.
close(1);
V etom primere polnost'yu opushchena obrabotka vozmozhnyh oshibok.
Dlya svyazyvaniya deskriptorov standartnogo vvoda ili vyvoda s
kanalom mezhprocessnoj svyazi zdes' ispol'zovana funkciya
dup(fd)", kotoraya vozvrashchaet duplikat deskriptora fd, prichem
ispol'zuetsya naimen'shij svobodnyj deskriptor fajla. Sledo-
vatel'no, posle zakrytiya fajla s deskriptorom 0 blizhajshee
obrashchenie k funkcii dup svyazhet deskriptor 0 s zadannym v
argumente dup deskriptorom. Posle vyzova dup nenuzhnyj
bol'she deskriptor fd[0] ili fd[1] zakryvayut.
15.3. Signaly i preryvaniya
Normal'nyj hod vypolneniya programmy v OS DEMOS mozhet
preryvat'sya "signalami". Signaly mogut poyavlyat'sya kak v
rezul'tate dejstviya vneshnih prichin (naprimer, v rezul'tate
nazhatiya na terminale klavishi, interpretiruemoj sistemoj kak
"preryvanie" - interupt), tak i v rezul'tate oshibok prog-
rammy.
Funkciya, izmenyayushchaya prinyatye po umolchaniyu dejstviya po
signalu, nazyvaetsya signal i imeet dva argumenta. Pervyj
specificiruet signal, a vtoroj predstavlyaet soboj libo
ssylku na funkciyu, libo special'noe vyrazhenie, oznachayushchee
trebovanie "ignorirovat'" signal libo "standartnaya reakciya
na signal". Uslovnye oboznacheniya zapisany v fajle vstavok
signal.h:
#include <signal.h>
signal (SIGNAL,REAKCIYA)
SIGNAL - eto odin iz standartnyh kodov signalov, naprimer
SIGINT, SIGKILL, ... (podrobnee sm. signal(2)). REAKCIYA -
eto libo ssylka na funkciyu, kotoraya budet vyzvana pri polu-
chenii signala, libo odin iz identifikatorov:
-74-
SIG_IGN - ignorirovat',
SIG_DFL - po umolchaniyu.
Vo vseh sluchayah funkciya signal vozvrashchaet staroe znachenie
opisatelya REAKCIYA. Sushchestvuyut nekotorye tonkosti, kotorye
illyustriruyutsya sleduyushchim fragmentom programmy:
#include <signal.h>
main()
{
int onintr(); /* Opisanie obyazatel'no */
if(signal(SIGINT,SIG_IGN) != SIG_IGN)
{ signal(SIGINT, onintr); }
...
exit(0);
}
onintr()
{ unlink(tempfile);
exit(1);
}
Proverka (if(signal...) svyazana s tem, chto signal SIGINT
posylaetsya na vse processy, nachatye s dannogo terminala.
Esli programma vypolnyaetsya v fonovom rezhime, interpretator
shell pri zapuske programmy ustanavlivaet v nej ignorirova-
nie signala SIGINT, dlya togo, chtoby s terminala preryvalis'
tol'ko interaktivnye processy. Pereklyuchenie obrabotki sig-
nala SIGINT na funkciyu onintr bez proverki perecherknulo by
vse dejstviya shell po zashchite fonovyh processov.
Eshche odna osobennost' svyazana s vozvratom iz programmy
obrabotki signala. Esli preryvanie proizoshlo vo vremya vypol-
neniya programmy, vozvrat iz funkcii obrabotki preryvaniya
privedet k normal'nomu prodolzheniyu ee vypolneniya. Esli,
odnako, preryvanie prishlo vo vremya operacii chteniya s termi-
nala, operaciya chteniya budet prervana, i proizojdet vozvrat
iz funkcii chteniya read s nulevym schetchikom bajtov. Kak pra-
vilo, funkciya obrabotki preryvanij dolzhna v takih sluchayah
ustanavlivat' kakoj libo flag, a programma chteniya, poluchiv
nulevoj schetchik bajtov posle operacii read, mozhet proverit'
etot flag i ustanovit', chto zhe proizoshlo - dostignut konec
fajla ili bylo preryvanie.
Esli programma obladaet sredstvami reakcii na preryva-
niya i, v to zhe vremya, vyzyvaet drugie programmy, zhelatel'no
upravlyat' reakciej na preryvanie primerno takim obrazom:
-75-
signal(SIGINT, onintr);
...
if(fork() == 0)
{ signal(SIGINT, SIG_DFL);
execl(...)
...
}
signal(SIGINT, SIG_IGN);
wait(&status);
signal(SIGINT, onintr);
V etom sluchae preryvaniya, posylaemye s terminala vo vremya
vypolneniya zapushchennoj parallel'no programmy, budut preryvat'
tol'ko etu programmu.
* 16. SVODKA SINTAKSICHESKIH PRAVIL
|ta svodka sintaksisa yazyka Si prednaznachena skoree dlya
oblegcheniya ponimaniya i ne yavlyaetsya tochnoj formulirovkoj
yazyka.
16.1. Vyrazheniya
Osnovnymi vyrazheniyami yavlyayutsya sleduyushchie:
vyrazhenie:
pervichnoe_vyrazhenie
* vyrazhenie
& vyrazhenie
- vyrazhenie
! vyrazhenie
~ vyrazhenie
++ l_znachenie
-- l_znachenie
l_znachenie ++
l_znachenie --
sizeof vyrazhenie
(imya tipa) vyrazhenie
vyrazhenie binarnaya_operaciya
vyrazhenie
vyrazhenie ? vyrazhenie : vyrazhenie
l_znachenie operaciya_prisvaivaniya
vyrazhenie
vyrazhenie , vyrazhenie
-76-
pervichnoe_vyrazhenie:
identifikator
konstanta
stroka
^ (vyrazhenie)
pervichnoe_vyrazhenie (spisok vyrazhenij)
neob
pervichnoe_vyrazhenie [vyrazhenie]
l_znachenie . Identifikator
pervichnoe vyrazhenie -> identifikator
l_znachenie:
identifikator
pervichnoe_vyrazhenie [vyrazhenie]
l_znachenie . Identifikator
pervichnoe_vyrazhenie -> identifikator
* vyrazhenie
(l_znachenie)
Operacii pervichnyh vyrazhenij
() [] . ->
imeyut samyj vysokij prioritet i gruppiruyutsya sleva napravo.
Unarnye operacii
* & - ! ~ ++ -- sizeof(imya tipa)
imeyut bolee nizkij prioritet, chem operacii pervichnyh vyrazhe-
nij, no bolee vysokij, chem prioritet lyuboj binarnoj opera-
cii. |ti operacii gruppiruyutsya sprava nalevo. Uslovnaya ope-
raciya gruppiruetsya sprava nalevo, vse binarnye operacii
gruppiruyutsya sleva napravo i ih prioritet ubyvaet v sleduyu-
shchem poryadke:
binarnaya operaciya:
* / %
+ -
>> <<
< > <= >=
== !=
&
~
|
&&
||
?:
Vse operacii prisvaivaniya imeyut odinakovyj prioritet i grup-
piruyutsya sprava nalevo:
= += -= *= ?= %= >>= <<= &= ~= |=
Operaciya zapyataya imeet samyj nizkij prioritet i gruppiruetsya
-77-
sleva napravo.
16.2. Opisaniya
Opisanie:
specifikatory_opisaniya spisok_inicia-
liziruemyh_opisatelej;
neob
Specifikatory_opisaniya:
specifikator_tipa specifikatory_opisaniya
neob
specifikator_klassa_pamyati specifi-
katory_opisaniya
neob
specifikator_klassa_pamyati:
auto
static
extern
register
typedef
specifikator_tipa:
char
short
int
long
unsigned
float
double
specifikator_struktury_ili_ob容dineniya
opredelyayushchee_tip_imya
specifikator_perechisleniya
spisok_inicializiruemyh_opisatelej:
inicializiruemyj_opisatel'
inicializiruemyj_opisatel',spi-
sok_inicializiruemyh_opisatelej
inicializiruemyj_opisatel'
opisatel'_inicializator
neob
opisatel':
identifikator
(opisatel')
* opisatel'
opisatel' ()
-78-
opisatel' [konstantnoe vyrazhenie ]
neob
specifikator_struktury_ili_ob容dineniya:
struct spisok_opisatelej_struktury
struct identifikator {spisok_opi-
sanij_struktury}
struct identifikator
union {spisok_opisanij_struktury}
union identifikator {spisok_opi-
sanij_struktury}
union identifikator
spisok_opisanij_struktury:
opisanie_struktury
opisanie_struktury spisok_opi-
sanij_struktury
opisanie struktury:
specifikator_tipa spisok_opisa-
telej_struktury
spisok_opisatelej_struktury
opisatel'_struktury
opisatel'_struktury,spisok_opisa-
telej_struktury
opisatel'_struktury:
opisatel'
opisatel': konstantnoe vyrazhenie
:konstantnoe_vyrazhenie
inicializator:
= vyrazhenie
= {spisok_inicializatora}
= {spisok_inicializatora}
spisok inicializatora:
vyrazhenie
spisok_inicializatora,spisok_ini-
cializatora
{spisok_inicializatora}
imya_tipa:
specifikator_tipa abstrakt-
nyj_opisatel'
-79-
abstraktnyj_opisatel':
pusto
{abstraktnyj_opisatel'}
* abstraktnyj_opisatel'
abstraktnyj_opisatel' ()
abstraktnyj_opisatel' [konstant-
noe_vyrazhenie]
neob
opredelyayushchee_tip_imya:
identifikator
specifikator_perechisleniya:
enum spisok_perechisleniya
enum identifikator spisok_perechisleniya
enum identifikator
spisok_perechisleniya:
perechislyaemoe
spisok_perechisleniya, perechislyaemoe
perechislyaemoe:
identifikator
identifikator = konstantnoe vyrazhenie
16.3. Operatory
sostavnoj_operator:
{spisok_opisanij spisok_operatorov}
neob neob
spisok_opisanij:
opisanie
opisanie spisok_opisanij
spisok_operatorov:
operator
operator spisok_operatorov
-80-
operator:
sostavnoj operator
vyrazhenie;
if (vyrazhenie) operator
if (vyrazhenie) operator else operator
while (vyrazhenie) operator
do operator while (vyrazhenie);
for(vyrazhenie1;vyrazhenie2;vyrazhenie3)
neob neob neob
operator
switch (vyrazhenie) operator
case konstantnoe_vyrazhenie : operator
default: operator
break;
continue;
return;
return vyrazhenie;
goto identifikator;
identifikator : operator
;
16.4. Vneshnie opredeleniya
programma:
vneshnee_opredelenie
vneshnee_opredelenie programma
vneshnee_opredelenie:
opredelenie_funkcii
opredelenie_dannyh
opredelenie_funkcii:
specifikator_tipa opisatel'_funk-
neob
cii telo_funkcii
opisatel'_funkcii:
opisatel' (spisok_parametrov)
neob
spisok_parametrov:
idetifikator
identifikator , spisok_parametrov
telo_funkcii:
spisok_opisanij_tipa operator_funkcii
operator_funkcii:
{spisok opisanij spisok_operatorov}
neob
-81-
opredelenie dannyh:
extern specifikator_tipa spi-
neob neob
sok inicializiruemyh opisatelej;
neob
static specifikator tipa spisok
neob neob
inicializiruemyh opisatelej;
neob
16.5. Preprocessor
#define identifikator stroka_leksem
#define identifikator(identifika-
tor,...,identifikator) stroka_leksem
#undef identifikator
#include "imya_fajla"
#include <imya_fajla>
#if konstantnoe_vyrazhenie
#ifdef identifikator
#ifndef identifikator
#else
#endif
#line konstanta "imya_fajla"
neob
* 17. Primery programm na Si
Primer 1: funkcii fgets i fputs (sm. razdel "Standart-
naya biblioteka vvoda/vyvoda. Vvod/vyvod strok").
-82-
#include <stdio.h>
char *fgets(s,n,iop) /*vzyat'<=n simvolov*/
char *s; /* iz iop */
int n;
register FILE *iop;
{
register int c;
register char *cs;
cs = s;
while(--n>0&&(c=getc(iop)) !=EOF)
if ((*cs++ = c)=='\n')
break;
*cs = '\0';
return((c==EOF && cs==s) ? NULL : s);
}
fputs(s,iop) /*pomestit' stroku s v */
register char *s; /* fajl iop */
register FILE *iop;
{
register int c;
while (c = *s++)
putc(c,iop);
}
Primer 2. Programma dlya razdeleniya odnogo bol'shogo fajla na
neskol'ko chastej tak, chtoby kazhdaya chast' nachinalas' so
stroki .sh 1 ...
-83-
#include <stdio.h>
#define NEWH ".sh 1" /*Priznak razdeleniya*/
/* Translyaciya:
cc -o ds ds.c
Zapusk:
ds otkuda kudapref kudasuff
rezul'tat:
ds a pref suff
perepisyvaet fajl a v fajly
pref00.suff, pref01.suff, ...
*/
main (ac,av)
char **av;
{
int nfile=0; /* Poryadkovyj nomer fajla*/
char str[512]; /* Bufer dlya stroki*/
if(ac != 4)
{
fprintf(stderr,
"Nevernoe chislo argumentov0);
exit(1);
}
/* freopen analogichno fopen, no izmenyaet
ukazannyj opisatel' fajla, a ne sozdaet
novyj. Zdes' my pereopredelyaem
stdin */
if(!freopen(av[1],"r",stdin))
{
fprintf(stderr,
"Ne mogu otkryt':%s0,av[1]);
exit(2);
}
/* Pereopredelili fajl stand. vyvoda */
of(av[2],nfile,av[3]);
while( gets(str))
{
/* strncmp(s1,s2,l) sravnivaet dve stroki
i vozvrashchaet 0, esli pervye l simvolov
sovpadayut */
if(strncmp(str,NEWH,strlen(NEWH))== 0)
{
fclose(fp);
nfile++;
/* |to prosto informacionnoe soobshchenie */
fprintf(stderr,
"Nachalo chasti %d0,nfile);
fp = of(av[2],nfile,av[3]);
}
puts(str);
if(ferror(stdout)) {
-84-
fprintf(stderr,
"Osh zapisi v fajl nomer %.2d0,nfile);
exit(4);
}
}
exit (0);
}
/* |ta funkciya sozdaet imya fajla
iz treh chastej i otkryvaet ego
kak standartnyj vyvod */
of(s1,n,s2)
char *s1,*s2;
{
register FILE *f;
char buf[100];
/* sprintf vozvrashchaet svoj pervyj argument */
if(( f = freopen(
sprintf(buf,"%s%02d.%s",s1,n,s2)
,"w",stdout))== NULL)
{
fprintf(stderr,
"Ne mogu otkryt' fajl:%s0,buf);
exit(4);
}
return;
}
-85-
SODERZHANIE
''ANNOTACIYA'' ................... 2
1. VVEDENIE .......................................... 1
2. SINTAKSICHESKAYA NOTACIYA ............................ 3
2.1. Klyuchevye slova .................................. 3
2.2. Konstanty ....................................... 4
2.2.1. Celye konstanty ............................... 4
2.2.2. Dlinnye (long) konstanty ...................... 4
2.2.3. Simvol'nye konstanty .......................... 4
2.2.4. Veshchestvennye konstanty ........................ 5
2.3. Stroki .......................................... 5
2.4. Harakteristiki apparatnyh sredstv ............... 6
3. OB'EKTY YAZYKA SI .................................. 6
3.1. Interpretaciya identifikatorov ................... 6
3.2. Ob容kty i l_znacheniya ............................ 8
3.3. Preobrazovaniya .................................. 8
3.3.1. Simvoly i celye ............................... 8
3.3.2. Tipy float i double ........................... 9
3.3.3. Veshchestvennye i celochislennye velichiny ......... 9
3.3.4. Ukazateli i celye ............................. 9
3.3.5. Celoe bez znaka ............................... 9
3.3.6. Arifmeticheskie preobrazovaniya ................. 10
4. VYRAZHENIYA ......................................... 10
4.1. Pervichnye vyrazheniya ............................. 11
4.2. Unarnye operacii ................................ 13
4.3. Mul'tiplikativnye operacii ...................... 14
4.4. Additivnye operacii ............................. 15
4.5. Operacii sdviga ................................. 16
4.6. Operacii otnosheniya .............................. 16
4.7. Operacii ravenstva .............................. 17
4.8. Pobitovaya operaciya 'i' .......................... 17
4.9. Pobitovaya operaciya isklyuchayushchego 'ili' ........... 17
4.10. Pobitovaya operaciya vklyuchayushchego 'ili' ............ 17
4.11. Logicheskaya operaciya 'i' ......................... 18
4.12. Operaciya logicheskogo 'ili' ...................... 18
4.13. Uslovnaya operaciya ............................... 18
4.14. Operaciya prisvaivaniya ........................... 19
4.15. Prisvaivanie struktury .......................... 20
4.16. Operaciya 'zapyataya' .............................. 20
4.17. Starshinstvo i poryadok vychisleniya. ............... 20
5. OPISANIYA .......................................... 22
5.1. Specifikatory klassa pamyati ..................... 22
5.2. Specifikatory tipa .............................. 23
5.3. Opisateli ....................................... 24
5.4. Smysl opisatelej ................................ 24
-86-
5.5. Opisanie struktur i ob容dinenij ................. 26
5.6. Perechislimyj tip ................................ 29
5.7. Inicializaciya ................................... 30
5.8. Imena tipov ..................................... 32
5.9. Opisatel' typedef ............................... 33
6. OPERATORY ......................................... 34
6.1. Operatornoe vyrazhenie ........................... 34
6.2. Sostavnoj operator (ili blok) ................... 34
6.3. Uslovnye operatory .............................. 35
6.4. Operator while .................................. 35
6.5. Operator do ..................................... 35
6.6. Operator for .................................... 35
6.7. Operator switch ................................. 36
6.8. Operator break .................................. 37
6.9. Operator continue ............................... 37
6.10. Operator vozvrata ............................... 38
6.11. Operator goto ................................... 38
6.12. Pomechennyj operator ............................. 38
6.13. Pustoj operator ................................. 38
7. VNESHNIE OPREDELENIYA ............................... 39
7.1. Vneshnee opredelenie funkcii ..................... 39
7.2. Vneshnie opredeleniya dannyh ...................... 40
8. OBLASTX DEJSTVIYA IDENTIFIKATOROV .................. 40
8.1. Leksicheskaya oblast' dejstviya .................... 41
8.2. Oblast' dejstviya vneshnih identifikatorov ........ 42
8.3. Neyavnye opisaniya ................................ 42
9. PREPROCESSOR YAZYKA 'SI' ........................... 43
9.1. Zamena leksem ................................... 43
9.2. Vklyuchenie fajlov ................................ 44
9.3. Uslovnaya kompilyaciya ............................. 45
9.4. Komanda #line ................................... 45
10. DOPOLNITELXNAYA INFORMACIYA O TIPAH ................. 46
10.1. Struktury i ob容dineniya ......................... 46
10.2. Funkcii ......................................... 47
10.3. Massivy, ukazateli i indeksaciya ................. 47
10.4. YAvnye preobrazovaniya ukazatelej ................. 48
11. KONSTANTNYE VYRAZHENIYA ............................. 49
12. SOOBRAZHENIYA O PERENOSIMOSTI ....................... 49
12.1. Anahronizmy ..................................... 51
13. STANDARTNAYA BIBLIOTEKA VVODA I VYVODA ............. 51
13.1. Obrashchenie k standartnoj biblioteke .............. 52
13.2. Standartnyj vvod i vyvod ........................ 52
13.3. Formatnyj vyvod - funkciya printf ................ 53
13.4. Formatnyj vvod - funkciya scanf .................. 55
13.5. Formatnoe preobrazovanie v pamyati ............... 58
-87-
13.6. Dostup k fajlam ................................. 59
13.7. Obrabotka oshibok - stderr i exit .............. 61
13.8. Vvod i vyvod strok .............................. 62
13.9. Funkciya ungetc .................................. 62
13.10.Raznye standartnye funkcii ...................... 62
13.10.1.Upravlenie pamyat'yu ............................ 62
13.10.2.Standartnye funkcii yazyka Si .................. 63
14. VZAIMODEJSTVIE S OPERACIONNOJ SISTEMOJ ............ 63
14.1. Podgotovka programm na Si v OS DEMOS ............ 64
14.2. Dostup k argumentam komandy ..................... 64
15. INTERFEJS SISTEMY DEMOS ........................... 66
15.1. Vvod/vyvod ...................................... 66
15.1.1. Deskriptory fajlov ............................ 66
15.1.2. Nizkourovnevyj vvod/vyvod. .................... 67
15.1.3. Otkrytie, sozdanie, zakrytie i udalenie ....... 68
15.1.4. Proizvol'nyj dostup - lseek ................... 69
15.2. Upravlenie processami ........................... 70
15.2.1. Funkciya system ................................ 71
15.2.2. Vyzov programmy na nizkom urovne - execl ...... 71
15.2.3. Porozhdenie novogo processa - fork ............. 71
15.2.4. Kanal mezhprocessnoj svyazi ..................... 73
15.3. Signaly i preryvaniya ............................ 74
16. Svodka sintaksicheskih pravil ...................... 76
16.1. Vyrazheniya ....................................... 76
16.2. Opisaniya ........................................ 78
16.3. Operatory ....................................... 80
16.4. Vneshnie opredeleniya ............................. 81
16.5. Preprocessor .................................... 82
17. Primery programm na Si ............................ 82
-88-