Операция присваивания

Результат вычисления выражений обычно должен где-то сохраняться. Для этой цели в языке предназначен оператор присваивания, обозначаемый знаком равенства '='. Слева от него ставится имя переменной или элемента массива, куда следует сохранить результат, а справа — само выражение, фактически, формула для расчета.

Мы уже использовали этот оператор для инициализации переменных, которая выполняется лишь однажды, в момент их создания. Однако присваивание позволяет изменять значения переменных в ходе алгоритма произвольное количество раз. Например:

int z;
int x = 1y = 2;
z = x;
x = y;
y = z;

Переменные x и y были проинициализированы значениями 1 и 2, после чего с помощью вспомогательной третьей переменной z и трех присвоений был произведен обмен значениями x и y.

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

int xyz;
x = y = z = 1;

Здесь единица будет присвоена сперва переменной 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):

// описание переменных
const double cx = 123.0;
int xya[5] = {1};
string s;
// присваивание
a[2] = 21;       // ok
x = a[0] + a[1] + a[2]; // ok
s = Symbol();    // ok
cx = 0;          // нельзя изменить const переменную
                 // error: 'cx' - constant cannot be modified
5 = y;           // 5 — это число (литерал)
                 // error: '5' - l-value required
x + y = 3;       // слева RValue (результат вычисления выражения)
                 // error: l-value required
Symbol() = "GBPUSD"// слева RValue с результатом вызова функции  
                     // error: l-value required

Компилятор выдает ошибку при нарушении правил использования оператора.