赋值运算符
赋值运算符分为两类:简单赋值运算符和复合赋值运算符。
简单赋值运算符
运算符 | 名称 | 作用 |
---|---|---|
a = b | 简单赋值运算符 | 将右侧数的值赋给左侧数 |
正如其名,这个运算符确实非常简单。赋值表达式的写法也很简单:
左侧操作数 = 右侧操作数
但是这个表达式若想合法需要满足这个要求:左侧操作数必须指明一个非只读的变量。这句话的意思就是,左侧操作数必须能够代表一块可以修改的内存空间。比如
3 = 3
(1 + 2) = 3
这些表达式是错误的,因为左侧操作数为字面量 3
或者表达式 1 + 2
并没有指明一个变量,没法赋值。
更具体地讲,左侧操作数必须是左值(lvalue),且定义了赋值运算符。关于左值,在指针章节有所介绍。
当左右两侧操作数类型不同时,会在赋值前进行隐式转换(Implicit conversion)。这里隐式转换的意思就是,以右侧操作数的值为基础生成一个和左侧操作数相同类型的临时值,然后再将这个临时值赋给左侧操作数。用图来形容的话就类似:
所以说,隐式转换并不会改变 b
的类型,只是为了赋值成功进行的一个中间过程。
若可能,隐式转换时临时值与右侧操作数的值会相等。仅仅当左侧操作数的数据范围放不下右侧操作数的值得时候,临时值才会改变。具体的隐式转换过程请参阅隐式转换章节。
复合赋值运算符
复合赋值运算符是将算术运算符与简单赋值运算符结合起来的运算符。目前你可以掌握以下五个:
运算符 | 名称 | 作用 |
---|---|---|
a += b | 加法复合赋值运算符 | 将右侧数加到左侧数上 |
a -= b | 减法复合赋值运算符 | 从左侧数减去右侧数 |
a *= b | 乘法复合赋值运算符 | 将右侧数乘到左侧数上 |
a /= b | 除法复合赋值运算符 | 从左侧数除以右侧数 |
a %= b | 模符合赋值运算符 | 从左侧数取余以右侧数 |
看上去很抽象,其实复合赋值运算符就相当于先进行算术运算,随后将运算结果赋值给左侧数。就是说,对于任何复合赋值表达式
左侧操作数 算术运算符= 右侧操作数
等价于
左侧操作数 = 左侧操作数 算术运算符 右侧操作数
举例来说:
a += 3
等价于a = a + 3
;a -= 1
等价于a = a - 1
;x *= y + 8
等价于x = x * (y + 8)
;x %= 3
等价于x = x % 3
。
这样看上去就比较容易理解了。
你应当还记得,任何表达式都有一个值,作为它的计算结果。不论简单还是复合,赋值表达式的值则是左侧操作数。也就是说,赋值表达式本身的值也指代了左侧操作数这个变量。例如:
上述程序的编译运行结果为:
10
20
因为赋值表达式的值为左侧操作数,所以还可以进行连续的赋值运算。
a = (b = (c = 5));
这个表达式将 5
赋给 c
,然后将 (c=5)
这个表达式赋给 b
。由于 c=5
这个表达式的值是 c
,所以相当于把 c
赋给了 b
。同理又把 b
赋给了 a
,就实现了连续的赋值。 不同于算术运算符,赋值运算符的结合方向是从右向左的。因此上述表达式还可以写成:
a = b = c = 5;
对于复合赋值运算符也可以连起来写:
((a *= 4) += 3) -= 5;
这就等价于:
a = a * 4;
a = a + 3;
a = a - 5;