Содержание
Возврат к предыдущей части 1.3.13 Инкремент и декремент
Операция простого присваивания используется для замены значения левого операнда, значением правого операнда. При присваивании производится преобразование типа правого операнда к типу левого операнда по правилам, упомянутым раньше. Левый операнд должен быть модифицируемым.
Пример:
1 2 3 4 | int t; char f; long z; t=f+z; |
Значение переменной f преобразуется к типу long, вычисляется f+z ,результат преобразуется к типу int и затем присваивается переменной t.
1.3.15. Составное присваивание
Кроме простого присваивания, имеется целая группа операций присваивания, которые объединяют простое присваивание с одной из бинарных операций. Такие операции называются составными операциями присваивания и имеют вид:
(операнд-1) (бинарная операция) = (операнд-2) .
Составное присваивание по результату эквивалентно следующему простому присваиванию:
(операнд-1) = (операнд-1) (бинарное операция) (операнд-2) .
Отметим, что выражение составного присваивания с точки зрения реализации не эквивалентно простому присваиванию, так как в последнем операнд-1 вычисляется дважды.
Каждая операция составного присваивания выполняет преобразования, которые осуществляются соответствующей бинарной операцией. Левым операндом операций (+=) (-=) может быть указатель, в то время как правый операнд должен быть целым числом.
Примеры:
1 2 3 4 | double arr[4]={ 2.0, 3.3, 5.2, 7.5 } ; double b=3.0; b+=arr[2]; /* эквивалентно b=b+arr[2] */ arr[3]/=b+1; /* эквивалентно arr[3]=arr[3]/(b+1) */ |
Заметим, что при втором присваивании использование составного присваивания дает более заметный выигрыш во времени выполнения, так как левый операнд является индексным выражением.
1.3.16. Приоритеты операций и порядок вычислений
В языке СИ операции с высшими приоритетами вычисляются первыми. Наивысшим приоритетом является приоритет равный 1. Приоритеты и порядок операций приведены в табл. 8.
Таблица 8
Приоритет | Знак операции | Типы операции | Порядок выполнения |
---|---|---|---|
2 | () [] . -> | Выражение | Слева направо |
1 | — ~ ! * & ++ — sizeof приведение типов |
Унарные | Справа налево |
3 | * / % | Мультипликативные | Слева направо |
4 | + — | Аддитивные | |
5 | << >> | Сдвиг | |
6 | < > <= >= | Отношение | |
7 | == != | Отношение (равенство) |
|
8 | & | Поразрядное И | |
9 | ^ | Поразрядное исключающее ИЛИ |
|
10 | | | Поразрядное ИЛИ | |
11 | && | Логическое И | |
12 | || | Логическое ИЛИ | |
13 | ? : | Условная | |
14 | = *= /= %= += -= &= |= >>= <<= ^= |
Простое и составное присваивание |
Справа налево |
15 | , | Последовательное вычисление |
Слева направо |
1.3.17. Побочные эффекты
Операции присваивания в сложных выражениях могут вызывать побочные эффекты, так как они изменяют значение переменной. Побочный эффект может возникать и при вызове функции, если он содержит прямое или косвенное присваивание (через указатель). Это связано с тем, что аргументы функции могут вычисляться в любом порядке. Например, побочный эффект имеет место в следующем вызове функции:
1 | prog (a,a=k*2); |
В зависимости от того, какой аргумент вычисляется первым, в функцию могут быть переданы различные значения.
Порядок вычисления операндов некоторых операций зависит от реализации и поэтому могут возникать разные побочные эффекты, если в одном из операндов используется операции увеличения или уменьшения, а также другие операции присваивания.
Например, выражение i*j+(j++)+(—i) может принимать различные значения при обработке разными компиляторами. Чтобы избежать недоразумений при выполнении побочных эффектов необходимо придерживаться следующих правил.
1. Не использовать операции присваивания переменной в вызове функции, если эта переменная участвует в формировании других аргументов функции.
2. Не использовать операции присваивания переменной в выражении, если эта переменная используется в выражении более одного раза.
Читать далее. Раздел 1.3.18. Преобразование типов
Содержание