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

книги / Программирование на языке Си

..pdf
Скачиваний:
15
Добавлен:
12.11.2023
Размер:
17.16 Mб
Скачать

32

Программирование на языке Си

В заголовочном файле float.li находятся директивы, опреде­ ляющие константы, связанные с представлением данных веще­ ственных типов. Например:

#define EXT_MIN 1.17549435E-38F

♦define DBL_MIN 2.2250738585072014E-308 ♦define DHL_EPSIL<PN 2 .2204460492503131E-16

Значения этих предопределенных на препроцессорном уров­ не констант в соответствии со стандартом языка в конкретных компиляторах могут быть несколько иными, отличными от тех, что приведены в-таблицах Приложения 2.

Подробно о возможностях прелроцессорных средств будет говориться в главе 3. Сейчас достаточно знать, что, записав в тексте своей программы директиву

♦include <limits.h>

можно использовать в программе стандартные именованные константы CHAR BIT, SHRT MLN и т.д. (см. Приложение 2), а уж их значениямиебудут те числа, которые включили в дирек­ тивы #define авторы конкретного компилятора и конкретной библиотеки.

Если включить в программу директиву

♦include <float.h>

то станут доступными именованные константы предельных значений числовых даннь(х вещественных типов (см. Прило­ жение 2).

Такой подход к определению предельных значений с помо­ щью препроцессорных констант, сохраняемых в библиотечных файлах; позволяет писать программы, не зависящие от реализа­ ции, что обеспечивает их достаточную мобильность. Програм­ мист использует в программе стандартные имена (обозначе­ ния) констант, а их значения определяются версией реализации, т.е. конкретным компилятором и его библиотеками.

Глава 1. Базовые понятия языка

33

1.4.О перации

Вэтом параграфе достаточно лаконично определяются все операции языка Си и приводится таблица их приоритетов. Хотя

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

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

группы в соответствии с их рангами.

 

За исключением операций "[]", "()" и

все знаки опера­

ций распознаются компилятором как отдельные лексемы. В за­ висимости от контекста одна и та же лексема может обозначать разные операции, т.е. один и тот же знак операции может упот­ ребляться в различных выражениях и по-разному интерпретиро­ ваться в зависимости от контекста. Например, бинарная опера­ ция & - это поразрядная конъюнкция, а унарная операция & - это операция получения адреса.

Операции ранга 1 имеют наивысший приоритет. Операции одного ранга имеют одинаковый приоритет, и если их в выра­ жении несколько, то они выполняются в соответствии с прави­ лом ассоциативности либо слева направо (->), либо справа налево (4-). Если один и тот же знак операции приведен в таб­ лице дважды (например, знак *), то первое появление (с мень­ шим по номеру, т.е. старшим по приоритету, рангом) соответствует унарной операции, а второе - бинарной.

Опишем кратко возможности отдельных операций.

3 -3 1 2 4

34

 

 

 

 

 

Программирование на языке Си

 

 

 

 

 

 

 

 

Таблица

1.4

 

 

 

Приоритеты (ранги) операций

 

 

 

Ранг

 

 

 

 

Операции

 

Ассоциа­

 

 

 

 

 

 

 

 

тивность

 

1

о

и

 

->

 

 

->

 

2

!

-

+

- + +

— & * ( т и п )

sizeof

<—

 

3

*

/

%

(мультипликативные бинарные)

->

 

4

+

-

(аддитивные бинарные)

 

->

 

5

«

»

(поразрядного сдвига)

 

->

 

6

<

<

- >

=

>

(отношения)

 

->

 

7

=

 

!=

(отношения)

 

->

 

8

&

(поразрядная конъюнкция "И")

 

->

-

9

Л

(поразрядное исключающее "ИЛИ")

 

->

 

10

|

(поразрядная дизъюнкция "ИЛИ")

 

 

11

&&

(конъюнкция "И")

 

->

 

12

||

(дизъюнкция "ИЛИ”)

 

 

13

?:

(условная операция)

 

<—

 

14

=

*=

/=

%=

+=

-= &= л= |= « =

» =

<—

 

15

,

(операция "запятая")

 

->

 

Унарные (одноместные) операции. Для изображения од­ номестных префиксных и постфиксных операций используются следующие символы:

&- операция получения адреса операнда (ранг 2);

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

2) ;

-унарный минус, изменяет знак арифметического операнда (ранг 2);

Глава 1. Базовые понятия языка

35

+- унарный плюс, введен для симметрии с унарным

минусом (ранг 2);

~- поразрядное инвертирование внутреннего двоичного кода целочисленного аргумента - побитовое отрица­

ние (ранг 2);

!- НЕ - логическое отрицание значения операнда (ранг 2). Применяется к скалярным операндам. Целочис­ ленный результат 0 (если операнд ненулевой, т.е. истинный) или 1 (если операнд нулевой, т.е. лож­ ный). Напомним, что в качестве логических значе­ ний в языке используют целые числа: 0 - ложь и не нуль, т.е. (!0) - истина. Отрицанием любого ненуле­ вого числа будет 0, а отрицанием нуля будет 1. Та­ ким образом: !1 равно 0; 12 равно 0; !(-5) равно 0; !0 равно 1;

++- увеличение на единицу (инкремент или автоувеличе­ ние - ранг 2); имеет две формы:

префиксная операция - увеличение значения опе­ ранда на 1 до его использования. Ассоциативность справа в соответствии со стандартом;

постфиксная операция - увеличение значения операнда на 1 после его использования. Ассоциатив­ ность слева в соответствии со стандартом.

Операнд для операции ++ (и для операции — ) не может быть константой либо произвольным выраже­ нием. Записи ++5 или 84++ будут неверными. ++(j+k) также неверная запись. Операндами унарных опера­ ций ++ и — должны быть всегда модифицируемые именующие выражения (L-value, left value, I-зна­ чение, леводопустимое выражение). Термины "лево­ допустимое выражение" и "/-значение" происходят от объяснения действия операции присваивания Е = D, в которой операнд Е слева от знака операции при­ сваивания может быть только модифицируемым /- значением. Примером модифицируемого /-значения служит имя переменной, которой выделена память^

3*

36

Программирование на языке Си

Таким образом, /-значение - ссылка на область памя­ ти, значение которой доступно изменениям;

-уменьшение на единицу (декремент или автоумень­ шение - ранг 7) - унарная операция, операндом ко­ торой должно быть леводопустимое выражение, т.е. не константа и не выражение:

префиксная операция - уменьшение на 1 значения операнда до его использования;

постфиксная операция - уменьшение на 1 значе­

ния операнда после его использования;

sizeof - операция (ранг 2) вычисления размера (в байтах) для объекта того типа, который имеет операнд. Разреше­ ны два формата операции:

sizeof выражение sizeoi(mun).

sizeof не вычисляет значения выражения, а только определяет его тип, для которого затем вычисляется размер.

Бинарные (двуместные) операции делятся на следующие группы:

аддитивные;

мультипликативные;

сдвигов;

поразрядные;

операции отношений;

логические;

присваивания;

выбора компонента структурированного объекта;

операция "запятая";

скобки в качестве операций.

Аддитивные операции:

+- бинарный плюс - сложение арифметических операндов или сложение указателя с целочисленным операндом

(ранг 4);

-- бинарный минус - вычитание арифметических операн­ дов или вычитание указателей (ранг 4).

Глава 1. Базовые понятия языка

37

Мультипликативные операции:

* - умножение операндов арифметического типа (ранг 3);

/- деление операндов арифметического типа (ранг 3). При целочисленных операндах абсолютное значение результата округляется до целого. Например, 20/3 рав­ но 6, -20/3 равно -6, (-20)/3 равно -6, 20/(-3) равно -6;

%- получение остатка от деления целочисленных операн­ дов (деление по модулю - ранг 3). При неотрицатель­ ных операндах остаток положительный. В противном случае остаток определяется реализацией. В компиля­ торе Turbo С:

13%4 равняется 1, (—13)%4 равняется -1;

13%(—4) равно +1, а (-13)%(-4) равняется -1.

При ненулевом делителе для целочисленных операн­ дов всегда выполняется соотношение: (a/b)*b + а%Ь равно а.

Операции сдвига (определены только для целочисленных операндов). Формат выражения с операцией сдвига:

операнд левый операция сдвига операнд правый

«- сдвиг влево битового представления значения левого целочисленного операнда на количество разрядов, рав­

ное значению правого целочисленного операнда

(ранг 5);

»- сдвиг вправо битового представления значения левого целочисленного операнда на количество разрядов, рав­

ное значению правого целочисленного операнда

(ранг 5).

Поразрядные операции:

&- поразрядная конъюнкция (И) битовых представлений значений целочисленных операндов (ранг 8);

I- поразрядная дизъюнкция (ИЛИ) битовых представле­ ний значений целочисленных операндов (ранг 10);

А- поразрядное исключающее ИЛИ битовых представле­ ний значений целочисленных операндов (ранг 9).

38

 

Программирование на языке Си

Результат выполнения операций сдвига и поразрядных one

раций:

равняется 16;

4 « 2

5 » 1

равняется

2;

6&5

равняется

4;

6 15

равняется'

7;

6-5

равняется

3.

Напоминаем, что двоичный код для 4 равен 100, для 5 - это 101, для 6 - это 110 и т.д. При сдвиге влево на две позиции код 100 становится равным 10000 (десятичное значение равно 16). Остальные результаты операций сдвига и поразрядных опера­ ций могут быть прослежены аналогично.

Обратите внимание, что сдвиг влево на п позиций эквивален­ тен умножению значения на 2", а сдвиг кода вправо уменьшает соответствующее значение в 2" раз с отбрасыванием дробной части результата. (Поэтому 5 » 1 равно 2.)

Операции отношений (сравнения):

<меньше, чем (ранг б);

>больше, чем (ранг б);

<= меньше или равно (ранг б); >= больше или равно (ранг б);

равно (ранг 7);

!= не равно (ранг 7).

Операнды операций отношений должны быть арифметиче­ ского типа или могут быть указателями. Результат целочислен­ ный: 0 (ложь) или 1 (истина). Последние две операции (операции сравнения на равенство) имеют более низкий при­ оритет по сравнению с остальными операциями отношений. Та­ ким образом, выражение (х < В — А < х) есть 1, когда значение х находится в интервале от А до В и А<В либо х, А, В равны. (Вначале вычисляются х < В и А < х , а к результатам применя­ ется операция сравнения на равенство — .)

Логические бинарные операции:

&&- конъюнкция (И) арифметических операндов или от­ ношений (ранг 11). Целочисленный результат 0 (ложь) или 1 (истина);

Глава 1. Базовые понятия языка

39

I I - дизъюнкция (ИЛИ) арифметических операндов

или

отношений (ранг 12). Целочисленный результат О (ложь) или 1 (истина).

(Вспомните о существовании унарной операции отрицания'!'.) Результаты отношений и логических операций:

3<5

равняется 1;

 

3>5

равняется 0;

 

3 = 5

равняется 0;

 

3!=5

равняется 1;

 

3!=5 || 3 = 5

равняется 1;

 

3+4>5 && 3+5>4 && 4+5>3

равняется 1.

Операции присваивания (ранг 14)

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

Перечислим операции присваивания, отметив, что сущест­ вуют одна простая операция присваивания и ряд составных опе­ раций:

=- простое присваивание: присвоить значение выраже­ ния-операнда из правой части операнду левой части. Пример: Р = 10.3 - 2*х;

*=

присваивание после умножения: присвоить операнду

 

левой части произведение значений обоих операндов.

 

Р *= 2 эквивалентно Р = Р * 2;

/=

- присваивание после деления: присвоить операнду ле­

 

вой части частное от деления значения левого опе­

 

ранда на значение правого. Р /= 2.2 - d эквивалентно

Р = Р / (2.2 - d);

%= - присваивание после деления по модулю: присвоить операнду левой части остаток от целочисленного де­ ления значения левого операнда на значение правого операнда. N %= 3 эквивалентно N = N % 3;

+= - присваивание после суммирования: присвоить опе­ ранду левой части сумму значений обоих операндов А += В эквивалентно А = А + В;

40

 

 

 

 

Программирование на языке Си

-=

-

присваивание после вычитания: присвоить операнду

 

 

левой части разность значений левого и правого опе­

 

 

рандов. X -= 4.3 - Z эквивалентно X = X - (4.3 - Z);

« =

-

присваивание после сдвигов разрядов влево: присво­

 

 

ить целочисленному операнду левой части значение,

 

 

полученное сдвигом влево его битового представле­

 

 

ния на количество разрядов, равное значению пра­

 

 

вого

целочисленного

операнда. Например, а « = 4

 

 

эквивалентно а = а «

4;

» =

-

присваивание после сдвигов разрядов вправо: присво­

 

 

ить целочисленному операнду левой части значение,

 

 

полученное сдвигом вправо его битового представле­

 

 

ния на количество разрядов, равное значению пра­

 

 

вого

целочисленного

операнда. Например, а » = 4

 

 

эквивалентно а = а »

4;

&=

-

присваивание после поразрядной конъюнкции: при­

 

 

своить целочисленному операнду левой части значе­

 

 

ние, полученное поразрядной конъюнкцией (И) его

 

 

битового представления с битовым представлением

 

 

целочисленного операнда правой части е &= 44 экви­

 

 

валентно е = е & 44;

 

1=

-

присваивание после поразрядной дизъюнкции: при­

 

 

своить целочисленному операнду левой части значе­

 

 

ние, полученное поразрядной дизъюнкцией (ИЛИ)

 

 

его битового представления с битовым представле­

 

 

нием целочисленного операнда правой части а | = b

 

 

эквивалентно а = а | Ь;

А=

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

после

исключающего поразрядного

 

 

“ИЛИ’’\ присвоить целочисленному операнду левой

 

 

части значение, полученное применением поразряд­

 

 

ной операции исключающего ИЛИ к битовым пред­

 

 

ставлениям

значений

обоих операндов z A= x + y

эквивалентно г - г А (х + у).

Обратите внимание, что для всех составных операций при­

сваивания

форма присваивания E l ор= Е2 эквивалентна Е1 =

E l op (Е2),

где ор - обозначение операции.

Глава 1. Базовые понятия языка

41

Операции выбора компонентов структурированного объ­ екта:

. (точка) - прямой выбор (выделение) компонента структу­ рированного объекта, например объединения или структуры (ранг 1). Формат применения опера­ ции:

имя структурированного объекта, имяком по ­ нента

-> - косвенный выбор (выделение) компонента струк­ турированного объекта, адресуемого указателем (ранг 1). При использовании операции требуется, чтобы с объектом был связан указатель (указателям посвящена гл. 4.). В этом случае фор­ мат применения операции имеет вид:

указатель на структурированный объект -> имякомпонента

Так как операции выбора компонентов структурированных объектов используются со структурами и объединениями, то необходимые пояснения и примеры приведем позже, введя пе­ речисленные понятия и, кроме того, аккуратно определив указа­ тели.

Запятая в качестве операции (ранг 15)

Несколько выражений, разделенных запятыми вычисля­ ются последовательно слева направо. В качестве результата со­ храняются тип и значение самого правого выражения. Таким образом, операция "запятая" группирует вычисления слева на­ право. Тип и значение результата определяются самым правым из разделенных запятыми операндов (выражений). Значения всех левых операндов игнорируются. Например, если перемен­ ная х имеет тип int, то значением выражения (х=3, 3*х) будет 9, а переменная х примет значение 3.

Скобки в качестве операций

Круглые () и квадратные [ ] скобки играют роль бинарных операций (ранг 1) при вызове функций и индексировании эле­ ментов массивов. Для программиста, начинающего использо-

Соседние файлы в папке книги