C++把赋值运算符连接而成的式子叫做赋值表达式,例如:a=b、a=b+c、a=3等。赋值运算符是一个双目运算符,必须两个参与运算的值,其左边的值叫做l-value,通常是变量或赋值表达式,常量和常变量不可以作为赋值表达式的左值。赋值运算符右端的值叫做r-value,通常一个常量、变量或表达式。
C++把逗号运算符连接的式子叫做逗号表达式,例如:“a,a*3”,“b+3,d/4”等。逗号表达式右被称为顺序求值表达式,它的值是最右端的表达式的值。例如,有如下逗号表达式:
a*=5,a+2
假设a=3,该逗号表达式的求值步骤是,先计算左侧的表达式a*=5,结果是a=15,然后计算右侧的表达式a+2,值是17,整条逗号表达式的值为17.
把赋值符和逗号连接的式子作为表达式看待是C++的特点之一,引入赋值表达式和逗号表达式使C++的语句变得十分灵活丰富。合理的使用赋值表达式和逗号表达式可以大大精简代码,使程序更紧凑。下面,我们来看一看使用这两种表达式时的技巧和应当注意到问题。
程序1:
#include <iostream> using namespace std;
int main() { unsigned short a; short b=-1; a=b; cout<<a<<endl; return 0; } |
大家可以先猜测一下程序的运行结果。
运行结果为65535.为什么是这个结果呢?其实,仔细想一想很容易得出答案:我们知道,short型变量在内存中是占两个字节的,即16个二进制位。因此,用-1给b赋值以后,b中的值就是1111,1111,1111,1111 「注」,然后将其赋给a, a所占内存也是16位,原封不动全部搬过去, a的值也变成1111,1111,1111,1111 ,a是无符号数,它的所有位都表示数值,1111,1111,1111,1111对应的十进制数即使65535,因此,输出结果就是65535.
【注】:所谓补码,就是将该负的数绝对值的原码取反后最低位加1得到的二进制编码。例如,求取-3的补码步骤如下:
第一步:计算出3的原码:0000,0000,0000,0011
第二步:将3的原码取反:1111,1111,1111,1100
第三步:将取反后的原码加1:1111,1111,1111,1101
1111,1111,1111,1101即是-3的补码。
例1的运行结果给了我们一个警示——不同类型的变量相互赋值时一定要考虑他们的编码形式即值域范围,否则可能得到与我们的期望相差十万八千里的结果。
例2:
#include <iostream> using namespace std;
int main() { int a=3; a+=4; cout<<a<<endl; return 0; } |
这个例子无甚特别之处,它仅仅说明了赋值运算符可以跟基本运算符组合成为符合赋值运算符。常见到组合方式有+=、-=、*=、/=、%=、<<=、>>=、&=、|=、∧=,关于这些符合赋值运算符的用法,此处不作介绍,大部分教授C++基础的书上都有,不清楚的可以自己去查看。下面,我们来看一个有趣的问题。有如下表达式:
a=5*8,a*10
问,该表达式的值是多少?
讨论对该表达式的求解,可能会有两种不同的声音:其一认为a=5*8是一个赋值表达式,它跟后面的a*10一起构成了一个逗号表达式,所以求解时先算出a=5*8的值,然后计算a*10的值;另一种声音认为5*8,a*10是个逗号表达式,应当先求这个逗号表达式的值,然后将逗号表达式的值赋给a.倒底那种理解对呢?这就需要查考两种运算符的运算优先级了。赋值运算符的优先级要高于逗号运算符,因此,对表达式a=5*8,a*10的求解应该是先计算a=5*8,然后计算逗号表达式的值。
例3:
#include <iostream> using namespace std;
int main() { int a; a=3; cout<<(a+=a=a+=a)<<endl; return 0; } |