Операция присваивания
Результат вычисления выражений обычно должен где-то сохраняться. Для этой цели в языке предназначен оператор присваивания, обозначаемый знаком равенства '='. Слева от него ставится имя переменной или элемента массива, куда следует сохранить результат, а справа — само выражение, фактически, формула для расчета.
Мы уже использовали этот оператор для инициализации переменных, которая выполняется лишь однажды, в момент их создания. Однако присваивание позволяет изменять значения переменных в ходе алгоритма произвольное количество раз. Например:
int z;
|
Переменные x и y были проинициализированы значениями 1 и 2, после чего с помощью вспомогательной третьей переменной z и трех присвоений был произведен обмен значениями x и y.
Оператор присваивания, как и все операторы, возвращает в выражение результат своей работы. Это дает возможность записывать присваивания в цепочку.
int x, y, z;
|
Здесь единица будет присвоена сперва переменной z, затем переменной y и, наконец, переменной x. Очевидно, что данный оператор является правоассоциативным, потому что присваиваемое значение "перетекает" в выражении справа налево.
Мы можем использовать присваивание как часть выражения, но поскольку приоритет его ниже всех других операторов (исключая только оператор "запятая", см. Приоритеты операций), необходимо заключать его в круглые скобки (подробности см. в разделе Группировка с помощью круглых скобок). Этот аспект делает возможными ситуации, когда опечатки в выражениях (скажем, одинарный символ '=' вместо '==') приводят к выполнению инструкций не так, как было задумано. Пример такого поведения приводится в разделе про инструкцию if.
Оператор присваивания накладывает определенные ограничения на то, что может стоять слева от знака '=', а что — справа. В программировании эти сущности для облегчения запоминания так и называются: LValue и RValue (от Left и Right, левое и правое).
LValue и RValue
LValue — представляет собой сущность, для которой выделена память, и как следствие, в неё можно записать значение. Известными нам примерами LValue являются переменная и элемент массива. После изучения ООП мы узнаем еще одного представителя этой категории: объект, в котором может быть перегружен оператор присваивания. Обязательным признаком LValue является наличие идентификатора.
Следует учитывать, что переменные и массивы могут быть описаны с ключевым словом const, и тогда они не могут выступать в качестве LValue, потому что модификация констант запрещена.
RValue — временная величина, используемая в выражении, такая как литерал или значение, возвращенное вследствие вызова функции или расчета фрагмента выражения.
Категория LValue носит расширительный характер: принадлежность к ней разрешает ставить соответствующий объект слева от знака '=', но не запрещает использовать его наравне с RValue справа от '='.
Категория RValue, напротив, имеет ограничительный характер: любая величина RValue может стоять только справа от '='.
Когда некий LValue-элемент используется справа от знака '=', его идентификатор обозначает фактически его текущее содержимое, помещенное в формулу выражения.
Когда же LValue-элемент используется слева от знака '=', его идентификатор указывает на адрес памяти (ячейку), куда следует записать новое значение — результат вычисления выражения.
Различные операторы имеют различные ограничения относительно того, могут ли они применяться к операндам-LValue или операндам-RValue. Например, операторы инкремента '++' и декремента '--' (см. Инкремент и декремент) допустимо использовать только с LValue.
Вот несколько примеров того, что можно и что нельзя делать с оператором присваивания (скрипт ExprAssign.mq5):
// описание переменных
|
Компилятор выдает ошибку при нарушении правил использования оператора.