设为首页 加入收藏

TOP

4.2 算术运算符
2013-10-07 16:29:28 来源: 作者: 【 】 浏览:120
Tags:4.2 算术 运算

4.2  算术运算符

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页)已经介绍过二元加法和减法运算符作用于指针的情况。当一元正号运算符作用于一个指针或者算术值时,返回运算对象值的一个(提升后的)副本。

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

  1. int i = 1024;  
  2. int k = -i;         // k是-1024  
  3. bool b = true;  
  4.  
  5. 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。在这样一台机器上,下面的复合赋值语句将产生溢出:

  1. short short_value = 32767;// 如果short类型占16位,则能表示的最大值是32767  
  2. short_value += 1;       // 该计算导致溢出  
  3. cout << "short_value: " << short_value << endl;  
  4. 给short_value赋值的语句是未定义的,这是因为表示一个带符号 

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

  1. short_value: -32768 

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

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

  1. int ival1 = 21/6;   // ival1是3,结果进行了删节,余数被抛弃掉了  
  2. int ival2 = 21/7;   // ival2 是3,没有余数,结果是整数值  

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

  1. int ival = 42;  
  2. double dval = 3.14;  
  3. ival % 12;          // 正确:结果是6  
  4. ival % dval;            // 错误:运算对象是浮点类型  

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

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

  1. 21 % 6;         /* 结果是3 */      21 / 6;         /* 结果是3 */  
  2. 21 % 7;         /* 结果是0 */      21 / 7;         /* 结果是3 */  
  3. -21 % -8;   /* 结果是-5 */         -21 / -8;   /* 结果是2 */  
  4. 21 % -5;    /* 结果是1 */      21 / -5;    /* 结果是-4 */  

4.2节练习

练习4.4:在下面的表达式中添加括号,说明其求值的过程及最终结果。编写程序编译该(不加括号的)表达式并输出其结果验证之前的推断。

12 / 3 * 4 + 5 * 15 + 24 % 4 / 2

练习4.5:写出下列表达式的求值结果。

(a) -30 * 3 + 21 / 5   (b) -30 + 3 * 21 / 5

(c) 30 / 3 * 21 % 5   (d) -30 / 3 * 21 % 4

练习4.6:写出一条表达式用于确定一个整数是奇数还是偶数。

练习4.7:溢出是何含义?写出三条将导致溢出的表达式。

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇4.1.3 求值顺序 下一篇4.3 逻辑和关系运算符(1)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: