赋值运算

表达式计算结果通常必须存储在某个位置。在编程语言中,由 = 表示的赋值运算符就是为此目的而设计的。变量或数组元素的名称置于运算符左侧(用于存储运算结果),而表达式(实际上是计算公式)置于右侧。

我们已经使用这个运算符来初始化变量,仅在创建变量的过程中执行过一次初始化。但赋值允许在算法过程中任意次数地更改变量值。例如:

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

变量 xy 初始化为值 1 和 2,随后用辅助的第三个变量 z 和三次赋值来交换 xy 值。

与所有运算符一样,赋值运算符也会将运算结果返回表达式。这样便能够串联书写赋值语句。

int xyz;
x = y = z = 1;

此处,1 首先被赋给变量 z,然后赋给变量 y,最后赋给变量 x。显然,这个运算符具有右结合性,因为被赋予的值在表达式中从右向左移动。

我们可以将赋值作为表达式的一部分。但是,由于其优先级低于所有其他运算符(除了“逗号”以外,参见 运算优先级),必须用圆括号括起来(有关详细信息,请参见 用圆括号分组一节)。这可能会导致以下情况:表达式中出现拼写错误(比如 == 误写为 =),导致无法按预期执行语句。此类行为的示例,请参见 语句 if 的相关章节。

赋值运算符对 = 左右两侧的实体施加了某些限制。在编程中,为了简化存储规则,这些实体的确切名称为:左值 (LValue) 和右值 (RValue)(左 (Left) 和右 (Right) 的英文单词首字母)。

左值和右值
 
左值代表一个实体,为其分配了内存,因此可以在其中写入值。左值的典型例子包括变量和数组元素。在学习了面向对象程序设计之后,我们将认识这一类别的另一个代表性实体:对象,对象中可以重新加载赋值运算符。左值的一个必要元素是标识符。
 
需要注意,变量和数组可以用 const 关键字描述,因此不能充当左值,因为常量禁止被修改。
 
右值是在表达式中使用的临时值,例如字面量、函数调的返回值或表达式片段的计算结果。
 
“左值”类别具有扩展性,即属于该类别的实体不仅可以放置在 = 左侧,而且不排斥将其与右值一样放置在 = 的右边。
 
“右值”类别则具有局限性,即任何右值都只能放置在 = 的右边。
 
当某个左值元素在 = 右侧使用时,其标识符实际上表示表达式公式中存储的当前内容。
 
但是,如果左值元素在 = 左侧使用,其标识符表示应写入新值(表达式计算结果)的内存地址(内存单元)。
 
不同运算符对于是否可用于左值或右值的操作数具有不同限制。例如,递增 ++ 和递减 - 运算符(参见 递增和递减)只能与左值一起使用。

以下是赋值运算符的允许和禁止操作的示例(ExprAssign.mq5 脚本):

// description of variables
const double cx = 123.0;
int xya[5] = {1};
string s;
// assignment
a[2] = 21;       // ok
x = a[0] + a[1] + a[2]; // ok
s = Symbol();    // ok
cx = 0;          // const variable may not be changed
                 // error: 'cx' - constant cannot be modified
5 = y;           // 5 ― this number (literal)
                 // error: '5' - l-value required
x + y = 3;       // to the left of RValue (expression computation result)
                 // error: l-value required
Symbol() = "GBPUSD"// to the left of RValue with the function call result  
                     // error: l-value required

编译器返回一个错误,指出违反了运算符使用规则。