频道栏目
读书频道 > 软件开发 > C++ > C++ Primer中文版(第5版)
4.2 算术运算符
2013-09-09 11:00:15     我来说两句
收藏   我要投稿

本文所属图书 > C++ Primer中文版(第5版)

这本久负盛名的 C++经典教程,时隔八年之久,终迎来史无前例的重大升级。除令全球无数程序员从中受益,甚至为之迷醉的——C++ 大师 Stanley B. Lippman 的丰富实践经验,C++标准委员会原负责人 Jos&eacut...  立即去当当网订购

 

表4.1:算术运算符(左结合律)
运算符 功能 用法
+ 一元正号 + expr
- 一元负号 - expr
* 乘法 expr * expr
/ 除法 expr / expr
% 求余 expr % expr
+ 加法 expr + expr
- 减法 expr – expr
 
表4.1(以及后面章节的运算符表)按照运算符的优先级将其分组。一元运算符的优先级最高,接下来是乘法和除法,优先级最低的是加法和减法。优先级高的运算符比优先级低的运算符组合得更紧密。上面的所有运算符都满足左结合律,意味着当优先级相同时按照从左向右的顺序进行组合。

除非另做特殊说明,算术运算符都能作用于任意算术类型(参见2.1.1节,第32页)以及任意能转换为算术类型的类型。算术运算符的运算对象和求值结果都是右值。如4.11节(第159页)描述的那样,在表达式求值之前,小整数类型的运算对象被提升成较大的整数类型,所有运算对象最终会转换成同一类型。

一元正号运算符、加法运算符和减法运算符都能作用于指针。3.5.3节(第119页)已经介绍过二元加法和减法运算符作用于指针的情况。当一元正号运算符作用于一个指针或者算术值时,返回运算对象值的一个(提升后的)副本。

一元负号运算符对运算对象值取负后,返回其(提升后的)副本:

int i = 1024;

int k = -i;     // k是-1024

bool b = true;

 

bool b2 = -b;       // b2是true!

在2.1.1节(第34页),我们指出布尔值不应该参与运算,-b就是一个很好的例子。

对大多数运算符来说,布尔类型的运算对象将被提升为int类型。如上所示,布尔变量b的值为真,参与运算时将被提升成整数值1(参见2.1.2节,第35页),对它求负后的结果是-1。将-1再转换回布尔值并将其作为b2的初始值,显然这个初始值不等于0,转换成布尔值后应该为1。所以,b2的值是真!

提示:溢出和其他算术运算异常                                                 

算术表达式有可能产生未定义的结果。一部分原因是数学性质本身:例如除数是0的情况;另外一部分则源于计算机的特点:例如溢出,当计算的结果超出该类型所能表示的范围时就会产生溢出。

假设某个机器的short类型占16位,则最大的short数值是32767。在这样一台机器上,下面的复合赋值语句将产生溢出:

short short_value = 32767;// 如果short类型占16位,则能表示的最大值是32767

short_value += 1;       // 该计算导致溢出

cout << "short_value: " << short_value << endl;

给short_value赋值的语句是未定义的,这是因为表示一个带符号数32768需要17位,但是short类型只有16位。很多系统在编译和运行时都不报溢出错误,像其他未定义的行为一样,溢出的结果是不可预知的。在我们的系统中,程序的输出结果是:

short_value: -32768

该值发生了“环绕(wrapped around)”,符号位本来是0,由于溢出被改成了1,于是结果变成一个负值。在别的系统中也许会有其他结果,程序的行为可能不同甚至直接崩溃。

当作用于算术类型的对象时,算术运算符+、-、*、/的含义分别是加法、减法、乘法和除法。整数相除结果还是整数,也就是说,如果商含有小数部分,直接弃除:

int ival1 = 21/6;   // ival1是3,结果进行了删节,余数被抛弃掉了

int ival2 = 21/7;   // ival2 是3,没有余数,结果是整数值

运算符%俗称“取余”或“取模”运算符,负责计算两个整数相除所得的余数,参与取余运算的运算对象必须是整数类型:

int ival = 42;

double dval = 3.14;

ival % 12;          // 正确:结果是6

ival % dval;            // 错误:运算对象是浮点类型

在除法运算中,如果两个运算对象的符号相同则商为正(如果不为0的话),否则商为负。C++语言的早期版本允许结果为负值的商向上或向下取整,C++11新标准则规定商一律向0取整(即直接切除小数部分)。

根据取余运算的定义,如果m和n是整数且n非0,则表达式(m/n)*n+m%n的求值结果与m相等。隐含的意思是,如果m%n不等于0,则它的符号和m相同。C++语言的早期版本允许m%n的符号匹配n的符号,而且商向负无穷一侧取整,这一方式在新标准中已经被禁止使用了。除了-m导致溢出的特殊情况,其他时候(-m)/n和m/(-n)都等于-(m/n),m%(-n)等于m%n,(-m)%n等于-(m%n)。具体示例如下:

21 % 6;     /* 结果是3 */         21 / 6;     /* 结果是3 */

21 % 7;     /* 结果是0 */         21 / 7;     /* 结果是3 */

-21 % -8;   /* 结果是-5 */        -21 / -8;   /* 结果是2 */

21 % -5;    /* 结果是1 */         21 / -5;    /* 结果是-4 */

您对本文章有什么意见或着疑问吗?请到论坛讨论您的关注和建议是我们前行的参考和动力  
上一篇:4.1.3 求值顺序
下一篇:4.2节练习
相关文章
图文推荐
排行
热门
最新书评
特别推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站