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;
}
问,输出结果是多少?
很多人见到诸如a+=a=a+=a这样的表达式时,还没思考,先就头脑发晕了。其实,大可不必这么惶恐,冷静下来,仔细想一想,这个表达式还是很容易求解的。要求解这个表达式,需要知道一个先决条件——赋值运算的求值顺序。赋值运算都是从右至左求值的。知道了这一点,问题就迎刃而解了。下面是对该表达式的求解过程:
第一步:计算最右端的a+=a,结果为6;
第二步:将a+=a的值赋给前一个a,a变为6;
第三步:计算最左端的a+=a,结果为12,12即为整个表达式的值。
好了,现在大家对连续多次赋值的赋值表达式的求解应该没有问题了。不过,上例中还有个需要注意的地方,不知道大家有没有留意, cout语句中 “a+=a=a+=a”是加括号的。在用cout输出赋值表达式或逗号表达式的值时一定要用括号将整个表达式括起来,否则,编译会出错,这主要是因为C++的输出流对象ostream中没有处理赋值运算符和逗号运算符的机制,如果你重载了<<运算符,实现了这个机制,就可以不要括号了(不过,要重载<<实现输出赋值表达式是个比较复杂的问题,远不如加个括号来得轻快,因此,牢记,输出赋值或逗号表达式时一定要用括号把正个表达式括起来)。
总结赋值表达式和逗号表达式的通常用法:
一、赋值表达式的用法:
1. 用于对多个变量赋值,如:a=b=c=d=3;
2. 用于条件语句的条件,如:if(a=fun(x,y)){},这时相当于执行
a=fun(x,y);
if(a){}
赋值表达式通常用于以上两种情况,但不限于此,灵活运用赋值表达式可以极大精简程序代码,使程序更加紧凑,更多用法,请自己去研究。
二、逗号表达式的用法:
1.用于顺序求值,如:a=b,b=c,c=d; 相当于执行:
a=b;
b=c;
c=d;
3. 用于条件语句,如:if(a=fun(x,y),a>0){},这时相当于执行
a=fun(x,y);
if(a>0){}
条件表达式通常用于以上两种情况,但不限于此,逗号语句的最大特点在于它可以在一条语句中整合多种不同类型的表达式,用一条语句实现多个功能。例如,有如下可编译执行程序:
#include <iostream>
using namespace std;
int main()
{
int i;
cout<<3<<endl,i=4*8,cout<<i<<endl;
return 0;
}
逗号表达式极大的增强了C++语句的灵活性,使用逗号表达式可以精简程序代码,希望大家在编程过程中灵活的使用逗号表达式,简化自己从程序代码,使代码更紧凑,更具可读性。