4.4 赋值运算符(2)
这个版本的while条件更容易表达我们的真实意图:不断循环读取数据直至遇到42为止。其处理过程是首先将get_value函数的返回值赋给i,然后比较i和42是否相等。
如果不加括号的话含义会有很大变化,比较运算符!=的运算对象将是get_value函数的返回值及42,比较的结果不论真假将以布尔值的形式赋值给i,这显然不是我们期望的结果。
因为赋值运算符的优先级低于关系运算符的优先级,所以在条件语句中,赋值部分通常应该加上括号。
切勿混淆相等运算符和赋值运算符
C++(www.cppentry.com)语言允许用赋值运算作为条件,但是这一特性可能带来意想不到的后果:
- if (i = j)
此时,if语句的条件部分把j的值赋给i,然后检查赋值的结果是否为真。如果j不为0,条件将为真。然而程序员的初衷很可能是想判断i和j是否相等:
- if (i == j)
程序的这种缺陷显然很难被发现,好在一部分编译器会对类似的代码给出警告信息。
复合赋值运算符
我们经常需要对对象施以某种运算,然后把计算的结果再赋给该对象。举个例子,考虑1.4.2节(第13页)的求和程序:
- int sum = 0;
- // 计算从1到10(包含10在内)的和
- for (int val = 1; val <= 10; ++val)
- sum += val; // 等价于sumsum = sum + val
这种复合操作不仅对加法来说很常见,而且也常常应用于其他算术运算符或者4.8节(第152页)将要介绍的位运算符。每种运算符都有相应的复合赋值形式:
- += -= *= /= %= //算术运算符
- <<= >>= &= ^= |= //位运算符,参见4.8节(第152页)
任意一种复合运算符都完全等价于
- aa = a op b;
唯一的区别是左侧运算对象的求值次数:使用复合运算符只求值一次,使用普通的运算符则求值两次。这两次包括:一次是作为右边子表达式的一部分求值,另一次是作为赋值运算的左侧运算对象求值。其实在很多地方,这种区别除了对程序性能有些许影响外几乎可以忽略不计。
4.4节练习
练习4.13:在下述语句中,当赋值完成后i和d的值分别是多少?
int i; double d;
(a) d = i = 3.5; (b) i = d = 3.5;
练习4.14:执行下述if语句后将发生什么情况?
- if (42 = i) // ...
- if (i = 42) // ...
练习4.15:下面的赋值是非法的,为什么?应该如何修改?
- double dval; int ival; int *pi;
- dval = ival = pi = 0;
练习4.16:尽管下面的语句合法,但它们实际执行的行为可能和预期并不一样,为什么?应该如何修改?
(a) if (p = getPtr() != 0) (b) if (i = 1024)