Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Электронный учебно-методический комплекс по учебной дисциплине «Системное программирование» для специальностей 1-40 01 01 «Программное обеспечение информационных технологий», 6-05-0612-01 «Программная инженерия»

.pdf
Скачиваний:
0
Добавлен:
28.12.2025
Размер:
3.06 Mб
Скачать

¦ [] выделение

элемента массива

¦

¦

или объединения

¦

¦ -> выделение

элемента структуры(объеди- ¦

¦

ния), адресуемой(ого) указателем

¦

----------------------------------------------------------------

2 ¦ !

логическое отрицание

¦Справа налево

¦ ~

побитовое отрицание (дополнение)

¦

¦ -

изменение знака

¦

¦ ++

увеличение на единицу

¦

¦ --

уменьшение на единицу

¦

¦ &

определение адреса (указателя)

¦

¦ *

обращение по адресу (указателю)

¦

¦ (тип) преобразование (приведение) типа

¦

¦ sizeof определение размера в байтах

¦

--------------------------------------------------------------

3 ¦ *

умножение

¦Слева направо

¦

/

деление

¦

¦

%

деление по модулю

¦

--------------------------------------------------------------

4 ¦

+

сложение

¦

- "

¦

-

вычитание

¦

 

--------------------------------------------------------------

5 ¦

<<

сдвиг

влево

¦

- "

¦

>>

сдвиг

вправо

¦

 

-------------------------------------------------------------

6 ¦ >

больше

¦

- "

¦ >=

больше или равно

¦

 

¦

<

меньше

¦

 

¦

<=

меньше или равно

¦

 

--------------------------------------------------------------

7 ¦

==

равно

¦

- "

¦

!=

не равно

¦

 

--------------------------------------------------------------

8 ¦ & побитовая конъюнкция (И) ¦ - "

--------------------------------------------------------------

9 ¦ ^ побитовое исключающее ИЛИ ¦ - "

--------------------------------------------------------------

10 ¦ | побитовая дизъюнкция (ИЛИ) ¦ - "

--------------------------------------------------------------

11 ¦ && логическая конъюнкция (И) ¦ - "

--------------------------------------------------------------

12 ¦ || логическая дизъюнкция (ИЛИ) ¦ - "

--------------------------------------------------------------

13 ¦ ?: условное вычисление ¦Справа налево

--------------------------------------------------------------

14 ¦ =

присваивание

¦

- "

¦ *=

умножение

и присваивание

¦

 

¦ /=

деление и

присваивание

¦

 

¦ %=

деление по модулю и присваивание

¦

 

¦ +=

сложение и присваивание

¦Справа налево

¦ -= вычитание

и присваивание

¦

 

¦ <<= сдвиг влево и присваивание

¦

 

¦ >>= сдвиг вправо и присваивание

¦

 

¦ &=

побитовая

конъюнкция и присваивание

¦

 

¦ ^=

побитовое

исключающее ИЛИ и

¦

 

¦

присваивание

¦

 

¦ |=

побитовая

дизъюнкция и присваивание

¦

 

--------------------------------------------------------------

15 ¦ , последовательное вычисление ¦Слева направо

--------------------------------------------------------------

Примеры:

x*y/c

<=>

(x*y)/c

/* ==> */

a=b=c

<=>

a=(b=c)

/*

<==

*/

alfa[i]() <=>

(alfa[i])()

/*

==>

*/

51

В сложных выражениях иногда играет роль порядок обработки операндов. Только для четырех операций (&& || ?: ,) в языке C левый операнд гарантированно обрабатывается первым. С целью обеспечения переносимости (мобильности) программы рекомендуется не использовать повторно в выражении переменную, значение которой присваивается любым образом в этом выражении. Пример:

y=(x=1)-(++x);

Перепишем оператор формирования результата в виде

y=ol-or;

Если компилятор планирует вычисление операндов в скобках слева направо, то схема формирования значения y:

ol=1; or=2; y=-1;

(переменная x последовательно принимает значения 1 и 2). При вычислении операндов в обратной последовательности

or=x+1; ol=1; y=x;

(переменная x вначале увеличивается на 1, затем принимает значение 1). Результат присваивания переменных x и y оказался существенно различен [1].

1.4 УПРАВЛЯЮЩИЕ ОПЕРАТОРЫ

1.4.1Условные операторы

Вязыке С имеется две разновидности условных операторов: простой и полный операторы условного выполнения. Синтаксис простого оператора условного выполнения:

if (выражение) оператор

Элемент "оператор" подлежит выполнению, если "выражение" от лично от нуля. Примеры записи:

if (x>0) x=0;

if (i!=1) j++, l=1; <===> if (i!=1) { j++, l=1; }

if (getch()!=27) { k=0;

}

if (i) exit(1); <===> if (i!=0) exit(1);

if (i>0) if (i<n) k++; <===> if ((i>0)&&(i<n)) k++; if (1) i=0; <===> i=0;

52

Синтаксис полного оператора условного выполнения:

if (выражение) оператор_1 else оператор_2

Если "выражение" отлично от нуля, то подлежит выполнению "оператор_1", иначе - "оператор_2". Примеры записи:

if (x>0) j=k+1; else m=i+10;

if (x) { y=i++; k=sfn(i);

} else { printf("\n ???");

exit(0);

}

Элементы "оператор_1" и(или) "оператор_2" могут быть любым оператором, в том числе и условным оператором. Фраза "else ..." относится к непосредственно предшествующей ей фразе "if ...", поэтому для устранения коллизий условных операторов разных уровней вложенности необходимо заключать их в фигурные скобки [1]:

if (!x)

if (!y) printf("\n

x=YES, y=YES");

else printf("\n x=NO"); /*

x=0 <===> (x!=0)&&(y==0) ??? */

if (!x)

{

 

if (!y) printf("\n x=YES,

y=YES");

}else printf("\n x=NO");

1.4.2Операторы цикла

Перечень разновидностей операторов цикла:

оператор цикла с предусловием;

оператор цикла с постусловием;

оператор цикла с предусловием и коррекцией. Синтаксис оператора цикла с предусловием:

while (выражение) оператор

(элемент "оператор" может быть пустым оператором, оператором-выражением или операторным блоком). Смысл оператора: на каждой итерации цикла предварительно проверяется условие продолжения цикла - ненулевое значение "выражения", затем выполняется "оператор". Элемент "оператор" может включать любое количество управляющих операторов, связанных с конструкцией while:

53

continue - переход к следующей итерации цикла; break - выход из цикла.

Примеры записи:

while (i>0) i<<=1, j++;

while (printf("\n n-?"), scahf(" %d",&n));

...

while (1) { /* Организация бесконечного цикла */ /* ... */

if (kbhit()&&(getch()==27)) break; /* Выход по ESC */ /* ... */

}

while (!kbhit()); /* Активное ожидание нажатия клавиши */

Синтаксис оператора цикла с постусловием:

do оператор while (выражение);

(элемент "оператор" может быть пустым оператором, оператором выражением или операторным блоком). Смысл оператора: на каждой итерации цикла предварительно выполняется "оператор", затем проверяется условие продолжения цикла - ненулевое значение "выражения". Назначение используемых в элементе "оператор" управляющих операторов continue и break совпадает с ранее рассмотренным, но оператор continue вызывает переход к этапу оценки "выражения".

do printf("\n ???");

while (!scanf(" %d",&n));

...

float *x; int i=0;

...

m=coreleft()/sizeof(*x); do {

printf("\n n-?");

if (!scanf(" %d",&n)) { sound(300);

printf(" Вводите цифры !"); continue;

}

if (n>m) continue;

if (!scanf(" %f",x+i)) break; } while (++i<n);

Синтаксис оператора цикла с предусловием и коррекцией:

for (инициализация; условие_выполнения; коррекция) оператор

Здесь "инициализация", "условие_выполнения" и "коррекция" выражения, которые могут отсутствовать (пустые выражения), но символы ';' опускать нельзя. Оператор-выражение "инициализация" выполняется один раз перед

54

началом итераций цикла. Итерации цикла продолжаются, пока истинно "условие_выполнения" - выражение пустое либо непустое выражение отлично от нуля. На каждой итерации последовательно выполняются "оператор" и оператор-выражение "коррекция". Назначение используемых в элементе "оператор" управляющих операторов continue и break совпадает с ранее рассмотренным.

float x[10], y; int i,n;

...

for (i=n=sizeof(x)/sizeof(*x); i>0; x[--i]=0);

...

for (i=0; i<n; x[i++]=0);

for (i=0; i<n; i++) x[i]=0;

...

for (i=0, i=0; i<n; i++)

if (x[i]<0) y+=x[i];

...

Различные формы операторов цикла могут выражаться друг через друга, например:

а) оператор

for (инициализация; условие_выполнения; коррекция) оператор

эквивалентен последовательности операторов

инициализация;

while (условие_выполнения) { оператор; коррекция;

}

(здесь "оператор" не может включать операторы break или continue); б) оператор

for (; условие_выполнения;) оператор

эквивалентен оператору

while (условие_выполнения) оператор;

в) оператор

for (оператор; условие_выполнения;) оператор

эквивалентен оператору

do оператор while (условие_выполнения);

г) оператор

for (;;) оператор

55

эквивалентен оператору

while (1) оператор;

(вместо 1 здесь может быть любое число, отличное от нуля).

При использовании вложенных циклов следует учитывать, что управляющие операторы break и continue действуют внутри собственного цикла. Для выхода из вложенного цикла приходится использовать оператор

безусловного перехода goto [1]:

float x[10][20]; int i,j;

/* Проверка наличия отрицательных значений */

for (i=0; i<10; i++) for (j=0; j<20; j++)

if (x[i][j]<0) goto next_step;

next_step: printf("\nЭлемент (%d,%d) отрицателен...");

1.4.3 Оператор выбора альтернатив (переключатель)

Синтаксис:

switch (выражение) { ------------------------------------

 

case константа_1: оператор_1

Тело

case константа_2: оператор_2

оператора

...

switch

default: оператор_N

 

} ------------------------------------------------------

 

Ключевое слово default и целочисленные значения констант рассматриваются как специальные метки операторов, область действия которых - тело оператора switch. Порядок следования таких меток не регламентирован. Целочисленное выражение сравнивается после вычис ления со значениями констант-меток. При совпадении с одной из них выполняется передача управления соответствующему оператору в теле оператора switch. В случае несовпадения значения выражения с одной из констант - переход на метку default либо, при ее отсутствии, к оператору, следующему за оператором switch. Упомянутые здесь специальные метки в теле оператора switch недолжны повторяться или использоваться для ссылок в операторе goto. Для выхода из тела оператора switch используют управляющий оператор break (дополнительно можно воспользоваться операторами goto или return, а при вложенности в оператор цикла и оператором continue). Рассмотрим пример построения

56

простейшего калькулятора для вычисления значений функций sin(), cos(), log(), sqrt(), tan().

#include <stdio.h> #include <math.h> #include <conio.h<

char f[]="\n %s(%lf)=%lf";

void main() { double x;

while (sound(1000), printf("\n x-? "), nosound(), scanf("%lf",&x)) {

for (;;) {

printf("\n x=%lf, Sin, Cos, Log, sQrt, Tan - ? ",x); switch(getch()) {

case 27 : goto cont; /* 27 - код клавиши ESC */ case 's':

case 'S': printf(f,"sin",x,sin(x)); break;

case 'c':

case 'C': printf(f,"cos",x,cos(x)); break;

case 'l':

case 'L': printf(f,"log",x,log(x)); break;

case 'q':

case 'Q': printf(f,"sqrt",x,sqrt(x)); break;

case 't':

case 'T': printf(f,"tan",x,tan(x)); break;

default: sound(100);

printf("\n Select Sin, Cos, Log, sQrt, Tan or ESC"); nosound();

}

}

cont:;

}

}

Очевидно, что здесь оператор switch можно заменить вложенными условными операторами:

int i;

...

i=getch();

if ((i=='s')||(i=='S')) printf(f,"sin",x,sin(x)); else if ((i=='c')||(i=='C')) printf(f,"cos",x,cos(x));

...

57

else if ((i=='t')||(i=='T')) printf(f,"tan",x,tan(x)); else {

sound(100); printf ...

nosound();

}

В последнем варианте используется последовательная проверка условий, его вычислительная сложность 6/2 (половина количества альтернатив). Оператор switch реализуется переходом по адресу, выбираемому из инвертированной таблицы меток по значению выражения, поэтому его вычислительная сложность близка к единице [1].

1.4.4 Операторы передачи управления

Формально к операторам передачи управления относятся: а) оператор безусловного перехода

goto метка;

б) оператор перехода к следующему шагу (итерации) цикла

continue;

(игнорирование оставшихся операторов тела цикла); в) выход из цикла либо оператора switch

break;

(передача управления следующему оператору); г) оператор возврата их функции

return;

return выражение;

(прекращение выполнения текущей функции и возврат управления вызвавшей программе с передачей, при необходимости, значения выражения).

Операторы вида a...в рассматривались ранее. Оператор return обязательно необходим в функциях, возвращающих значения. В функциях, не возвращающих результат, он неявно присутствует после последнего оператора. Значение "выражения" при необходимости будет преобразовано к типу возвращаемого функцией значения.

void error(void *x, int n) {

if (!x) printf("\nМассив не создан"); if (!n) printf("\nМассив пустой");

}

float estim(float *x, int n) { int i;

58

float y;

if ((!x)||(!n) { error(x,n); return 0;

}

for (y=i=0; i<n; i++) y+=x[i];

return y/n;

}

Строго говоря, в языке C имеются дополнительные возможности передачи управления:

нелокальный переход, организуемый парой функций longjump и setjump;

операторы структурного управления исключениями _try/_except и _try/finally [1].

1.5 СТРУКТУРИЗАЦИЯ ПРОГРАММ И ДАННЫХ

1.5.1Области действия объектов программ

Вязыке С можно выделить два уровня детализации модуля программы: файл исходного текста и функцию. Файл исходного текста может включать определения данных и функций. Операционные объекты, кроме атрибута типа, имеют атрибуты области действия и класса памяти. По области действия

разделяют объекты:

глобальные - доступны во всех функциях файла исходного текста;локальные - доступны только в теле функции или операторного блока.

Вязыке С нет ключевого слова, указывающего область действия объекта. Область действия определяется местоположением оператора описания объекта в файле исходного текста программы (любой объект полностью описывается в одном операторе).

Структура исходного текста программ на языке С

-----------------------------------------

 

 

 

------------------

¦

Описание глобальных объектов

 

¦

 

-----------------------------------------

 

-----------------------------------------

 

¦

Заголовок функции {

 

¦

 

¦

 

 

¦

Директивы

¦

----------------------------------

 

¦

 

¦

¦ Описание локальных объектов

¦

¦

препроцессора

¦

----------------------------------

 

¦

 

¦

----------------------------------

 

¦

и макрокоманды

¦

¦ Операторы

¦

¦

 

¦

----------------------------------

 

¦

 

¦

 

 

¦

 

¦

}

 

¦

 

-----------------------------------------

 

 

 

------------------

59

/* Локальное n */
/* Глобальное n */
/* Локальное n */

Файл исходного текста может включать любое количество определений функций и(или) глобальных данных. Параметры функции являются локальными объектами и должны отличаться по именам от используемых в теле функции глобальных объектов. Локальные объекты, описанные в теле функции, имеют приоритет перед объектами, описанными вне функции:

int n;

/* Глобальное n */

void main (int n, char **l) { int i;

/* ... */ f1(i); /* ... */ f2(n);

}

f1(int i) { /* ... */ i=n;

/* ... */

}

f2(int n) { int i;

/* ... */ i=n;

/* ... */

}

Локальные объекты в программах на языке С можно декларировать в начале любого операторного блока, а операторный блок тела функции - частный случай такого правила (в языке С++ оператор декларации может размещаться в любом месте операторного блока). В любом месте файла исходного текста можно ссылаться на глобальные объекты, определенные ниже в остатке текущего файла или в других файлах. Для этого необходимо описать тип объекта и добавить к описанию ключевое слово extern. Описания функций подразумевают атрибут extern по умолчанию. Разрешается опускать длину внешних одномерных массивов, но операция sizeof к таким массивам становится бессмысленной. Следует учитывать, что любой оператор описания действует только на остаток файла исходного текста [1].

1.5.2 Классы памяти объектов программ

Классы памяти объектов в языке C:

статическая память - распределяется на этапе трансляции и заполняется по умолчанию нулями;

60

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]