Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
c-operators.doc
Скачиваний:
8
Добавлен:
09.11.2019
Размер:
154.62 Кб
Скачать

Примеры.

1. Выражение (i<0) ? 0:100 для неотрицательных значений I имеет значение 100, а для отрицательных — нуль.

2. Выражение (f<g)? f:g возвращает меньшее из f и g.

Условная операция имеет невысокий приоритет — ниже только приоритет операций присваивания и операции "запятая". Поэтому в приведенных примерах скобки вокруг <выражения_1> были необязательны. Однако их применение улучшает читаемость программ.

Если <выражение_2> и <выражение_3> имеют различные типы, то тип результата определяется по типу более "длинного" операнда.

Пример.

Пусть переменная i имеет тип int, а переменная g — float. Тогда результатом вычисления выражения

f<g ? I : g

будет значение типа float, причем тип переменной f, которая участвует только в первом выражении никак не влияет на тип результата.

Условная операция порождает обычное выражение языка Си и поэтому может применяться в любом месте, где синтаксисом разрешено использование выражений, например, при присваивании min = f<g?f:g.

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

i<j?i<k?i:k:j

будет трактоваться как

(i<j)?(i<k?i:k):j

Задание.

Определить результат (тип и значение) в следующих выражениях (при i=1

И i=6):

a) (i>4?1:0)

б) (i+2>5)||(i+3<=4)?10*i:10/i

в) (2+i)\%3?i<<1:i>>1

г) x=i*i*(i>0?i:-i)

Побочные эффекты. Приоритеты и порядок выполнения операций

В Си не фиксируется порядок вычисления операндов (исключая &&, || , ? и запятую). Это означает, что при выполнении оператора

x = f( ) + g( )

функция f может быть вычислена раньше g или наоборот. Порядок вычисления выражений определяется конкретной реализацией. Эта неопределенность заключает в себе опасность, связанную с побочными эффектами.

Побочные эффекты — это изменения в состоянии объектов, которые возникают при вычислении выражений.

Так как в Си присваивание — операция, то все присваивания обладают запланированнными побочными эффектами. Заметим, что кроме этого при присваивании могут возникать и дополнительные побочные эффекты, которые могут стать причиной трудно обнаруживаемых ошибок.

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

Пример.

Побочные эффекты возникают при следующем вызове функции f(i+1, i=j+2).

Аргументы в вызове функции могут быть вычислены в любом порядке. Выражение i+1 может быть вычислено до вычисления i = j + 2, либо наоборот. Результат окажется различным.

Поскольку операции инкремента и декремента включают присваивание, то они также могут вызвать побочные эффекты.

Пример.

В следующем фрагменте значение переменной a непредсказуемо:

d=0; a=b++=c++=d++;

Цепочка присваиваний может приводить к различным результатам.

Первый способ: c получает значение d, а затем обе переменные инкрементируются.

Далее b присваивается значение с и затем b инкрементируется. И, наконец, результат 2 присваивается переменной а.

Второй способ: Сначала выполняется цепочка присваиваний, а затем операции инкремента. В этом случае последнее присваивание имеет вид a=0.

Оба метода с точки зрения стандарта языка являются правильными. Стандарт сознательно устроен так, что большинство подобных вопросов оставлено на усмотрение разработчиков компиляторов, так как лучший порядоквычислений определяется архитектурой машины.

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

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

Операции с одинаковым приоритетом выполняются слева направо в порядке следования.

Приоритет

Оператор

Описание

1

++

Инкремент

--

Декремент

()

Вызов функции или подвыражение

[]

Выделение элемента массива

->

Указатель структуры

.

Член структуры

2

!

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

Поразрядное логическое НЕ (двоичная инверсия)

-

Унарный минус (изменение знака)

+

Унарный плюс

(type)

Преобразование к типу

*

Разыменование указателя

&

Определение адреса переменной

sizeof

Определение размера в байтах

3

*

Умножение

/

Деление

%

Остаток от деления

4

+

Сложение

-

Вычитание

5

>>

Поразрядный сдвиг вправо

<<

Поразрядный сдвиг влево

6

<

Меньше

>

Больше

<=

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

>=

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

7

==

Равно

!=

Не равно

8

&

Поразрядное логическое И

9

^

Поразрядное исключающее ИЛИ

10

|

Поразрядное логическое ИЛИ

11

&&

Логическое И

12

||

Логическое ИЛИ

13

?:

Оператор условия

14

=

Присваивание

+=

Составное сложение

-=

Составное вычитание

*=

Составное умножение

/=

Составное деление

%=

Составное определение остатка от деления

>>=

Составной поразрядный сдвиг вправо

<<=

Составной поразрядный сдвиг влево

&=

Составное поразрядное логическое И

^=

Составное поразрядное исключающее ИЛИ

|=

Составное поразрядное логическое ИЛИ

15

,

Операция "запятая"

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