ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 13.12.2020
Просмотров: 4237
Скачиваний: 28
Глава 3. Операторы и выражения
51
3.10. Составные операторы
присваивания
В языке программирования С также используются
составные
операторы
присваивания, которые объединяют арифметический
или побитовый оператор с оператором присваивания. В общем
случае составной оператор присваивания имеет следующий вид:
операнд_1 оператор= операнд_2
Здесь
оператор
обозначает один из арифметических или побито-
вых операторов. Далее перечислены все составные операторы
присваивания, определенные в языке программирования С:
+=
— прибавление числа и присваивание;
-=
— вычитание числа и присваивание;
*=
— умножение на число и присваивание;
/=
— деление на число и присваивание;
%=
— деление по модулю на число и присваивание;
<<=
— сдвиг влево числа и присваивание;
>>=
— сдвиг вправо числа и присваивание;
&=
— побитовое И и присваивание;
^=
— побитовое исключающее ИЛИ и присваивание;
|=
— побитовое ИЛИ и присваивание.
Работают составные операторы присваивания следующим обра-
зом. Сначала выполняется операция над левым и правым операн-
дами составного оператора присваивания, а затем полученный
результат присваивается левому операнду. Например:
int x = 1, y = 2;
y += x; /* y = 3 */
Это эквивалентно выражению:
y = y + x;
Отметим, что приоритет составных операторов присваивания
совпадает с приоритетом простого оператора присваивания.
Часть I. Язык программирования С
52
Поэтому выражение:
a *= b - c;
,
эквивалентно выражению:
a = a * (b - c);
Смысл введения составных операторов присваивания в язык про-
граммирования C заключается в следующем. В микропроцессо-
рах существуют команды, которые работают аналогично состав-
ным операторам присваивания. Причем эти команды работают
быстрее, чем команды, которые выполняют операцию над двумя
операндами и результат этой операции заносят в третий операнд.
Так как язык программирования C разрабатывался как язык ас-
семблера высокого уровня, то аналоги упомянутых команд мик-
ропроцессора и были введены в синтаксис языка С.
3.11. Операторы инкремента
и декремента
Над переменными арифметических типов определены также
унарные операторы:
++
— инкремент, т. е. увеличение значения числа на единицу;
--
— декремент, т. е. уменьшение значения числа на еди-
ницу.
Эти операторы могут быть как
префиксными
, так и
постфиксны-
ми
, т. е. записываться как перед операндом, так и после него.
Операндом как префиксного, так и постфиксного оператора ин-
кремента или декремента должно быть модифицируемое L-value.
Результатом как префиксного, так и постфиксного оператора яв-
ляется R-value. При этом префиксные операторы инкремента и
декремента дают в результате измененное значение переменной,
а результатом постфиксных операторов инкремента и декремента
является старое значение переменной.
Следующий пример демонстрирует разницу между префиксными
и постфиксными операторами инкремента и декремента:
int a, b = 1;
a = b++; /* a = 1, b = 2 */
Глава 3. Операторы и выражения
53
a = ++b; /* a = 3, b = 3 */
a = b--; /* a = 3, b = 2 */
a = --b; /* a = 1, b = 1 */
Приоритет префиксных операторов инкремента и декремента
совпадает с приоритетом унарных операторов. А приоритет
постфиксных операторов инкремента и декремента выше при-
оритета унарных операторов и, следовательно, выше приоритета
префиксных операторов инкремента и декремента. Поэтому вы-
ражение:
++x++
,
вызовет ошибку компиляции, т. к. результатом постфиксного
оператора декремента является R-value.
В языке программирования C++ результатом префиксного опера-
тора инкремента или декремента является L-value. Поэтому эти
операторы могут встречаться слева от оператора присваивания.
Учитывая это замечание, в языке программирования С++ можно
написать следующее выражение:
int x = 2, y = 3;
++y += x; /* x = 2, y = 6 */
3.12. Условный оператор
Условный оператор
является тернарным, обозначается двумя
символами:
?
и
:
, и имеет следующий вид:
операнд_1 ? операнд_2 : операнд_3
Вычисляется условный оператор следующим образом. Сначала
вычисляется логическое значение
операнда_1
. Если это значение
истинно, то вычисляется
операнд_2
, значение которого и является
значением условного оператора. В противном случае вычисляет-
ся
операнд_3
и его значение является значением условного опера-
тора. Например, в следующем примере с помощью условного
оператора вычисляется минимум из чисел
x
и
y
.
Часть I. Язык программирования С
54
int x= 1, y = 2, min;
min = (x < y) ? x : y; /* min = 1 */
Допускаются следующие типы второго и третьего операндов ус-
ловного оператора:
оба операнда имеют арифметический тип;
оба операнда имеют тип
void
;
оба операнда являются указателями на сравнимые типы;
оба операнда являются структурами или объединениями одно-
го типа;
один операнд является указателем, а второй — пустым указа-
телем;
один операнд является указателем, а второй указателем на тип
void
.
Об указателях и структурах будет рассказано далее. Теперь же
отметим, что приоритет условного оператора ниже, чем приори-
тет бинарных операторов, но выше приоритета оператора при-
сваивания.
Результатом вычисления условного оператора является R-value.
При вычислении условного оператора выполняются следующие
преобразования типов значений второго и третьего операндов,
независимо от того, какой из операндов вычисляется:
если оба операнда имеют арифметический тип, то результат
имеет тип операнда с наибольшим диапазоном значений;
если один из операндов является указателем на тип
void
, то
результат также будет иметь тип указателя на тип
void
;
если один из операндов является указателем, а другой — пус-
тым указателем, то результат имеет тип не пустого указателя.
Ассоциативны условные операторы справа налево. Поэтому сле-
дующее выражение:
int x = 1, y = 2, z = 3;
x < y ? y < z ? --x : --y : --z; /* x = 0, y = 2, z = 3 */
эквивалентно выражению:
x < y ? (y < z ? --x : --y) : --z; /* x = 0, y = 2, z = 3 */
Глава 3. Операторы и выражения
55
В языке программирования C++ результатом условного оператора
может быть и L-value, если результатом вычисления как
операн-
да_2
, так и
операнда_3
являются L-value одного типа. В против-
ном случае результатом вычисления условного оператора являет-
ся R-value.
Учитывая это замечание, в языке программирования С++ можно
написать так:
int x = 1, y = 2;
((x < y) ? x : y) = 0; /* x = 0, y = 2 */
но:
int x = 1, y = 2;
(x < y) ? x : y = 0; /* x = 1, y = 2 */
т. к. условный оператор имеет приоритет выше, чем оператор
присваивания.
3.13. Оператор "запятая"
Оператор "запятая"
обозначается символом
,
и имеет следую-
щий вид:
операнд_1, операнд_2
,
где операнды могут быть произвольными выражениями. Работает
оператор "запятая" следующим образом. Сначала вычисляется
значение
операнда_1
, а затем значение
операнда_2
. Значением
оператора
,
является R-value, равное значению
операнда_2
, а зна-
чение
операнда_1
игнорируется. Например:
int x = 1, y = 2, z;
z = (x++, x - y); /* z = 0 */
но:
z = x++, x - y; /* z = 1 */
т. к. оператор "запятая" имеет наименьший приоритет из всех
операторов. Оператор
,
имеет ассоциативность слева направо.