【原创,谢绝转载】C++自学笔记——运算数的计算顺序 与 运算符的执行顺序

本篇博文相关内容收录在《C++自学笔记(上册)面向过程》6.1.2小节和7.7.5小节。这本书暂时还未出版,因此与该书有关的任何图片、表格、代码、文章(包括本篇)都谢绝转载。

首先明确一点,“运算数的计算顺序”与“运算符的执行顺序”是两个概念,不要混为一谈。

C++标准只针对四种表达式规定了运算数的计算顺序,这四种表达式分别是:与表达式、或表达式、逗号表达式、条件表达式。如果用L、R、V代表三个运算数,那么:

1、在与表达式L&&R中,总是先计算L,然后在L为真时才计算R,在L为假时不计算R。

2、在或表达式L||R中,总是先计算L,然后在L为假时才计算R,在L为真时不计算R。

3、在逗号表达式L,R中,总是先计算L再计算R,L和R二者都会被计算。

4、在条件表达式V?L:R中,总是先计算V,然后在V为真时才计算L同时不计算R,在V为假时才计算R同时不计算L。L和R二者总是只有一个被计算(而另一个不会被计算)。

除此之外的其它任何表达式(假设含有多个运算数),C++标准都没有规定运算数的计算顺序。

示例1,算术表达式9/2+5*7含有三个运算符:除法、加法、乘法。加法优先级最低,因而这是一个加法表达式,该表达式等价于(9/2)+(5*7)。这个加法表达式的左运算数是(9/2),右运算数是(5*7)。但是,C++标准并没有规定:加法表达式的两个运算数究竟哪个先执行。因此,该表达式的执行过程允许出现两种可能:先算除法得到4+(5*7),先算乘法则得到(9/2)+35。只不过,对于该表达式来说,这两种可能的执行过程所带来的最终结果是一致的,都是4+35得到39。

也许有初学者会反驳上述观点,理由是:除法和乘法优先级相同,并且结合性都是左结合,因此上述表达式必须先算左边的除法。我只能说,这个牵强的理由恰好落入一个陷阱:将“运算数的计算顺序”与“运算符的执行顺序”混为一谈。

C++标准通过运算符的优先级/结合性来决定运算符的执行顺序。但只有当两个运算符相邻时,比较二者的优先级才有意义。并且,当两个相邻运算符的优先级相同时,二者的结合性才会发挥作用。

在表达式9/2+5*7中,除法与加法相邻,除法的优先级高于加法,因而标准一定能保证除法的执行优先于加法。同理,加法与乘法相邻,乘法的优先级高于加法,因而标准一定能保证乘法的执行优先于加法。但是,除法与乘法始终不会相邻,因而标准无需规定这二者究竟谁先执行。

示例2:如果整数变量num的值是3,则表达式++num+num%2的值是多少?与示例1类似,这仍然是一个加法表达式,该表达式等价于(++num)+(num%2)。这个加法表达式的左运算数是(++num),右运算数是(num%2)。尽管前置自增运算符“++”优先于取余运算符“%”,但是这二者在该表达式之中并不相邻,因此标准对这二者的执行顺序没有任何规定。该表达式的执行过程允许出现两种可能:假设系统决定先算(++num),则该表达式的值为4+(4%2)得4+0等于4。假设系统决定先算(num%2),则该表达式的值为4+(3%2)得4+1等于5。注意,这两种可能的执行过程带来的结果并不一致。这其实意味着,该表达式的值是【标准未规定】的,程序员应该主动避免编写这种表达式。

事实上,我简单测试了一下我选择的系统,在将num设置为3之后执行(++num)+(num%2)得到的值是4。然而,如果交换这个加法表达式的左右两个运算数,那么在将num设置为3之后执行(num%2)+(++num)得到的值却是5。这似乎在表明一个仅适用于我所选系统的现象:对于加法表达式,我选择的系统会先计算左运算数、再计算右运算数。其实不然!我继续测试,在将num设置为3之后执行num+(num*=2)得到的值却是12,这恰好违背了刚才那个现象。

因此,真相是:在示例2中所列举出的这三个加法表达式(++num)+(num%2)、(num%2)+(++num)、num+(num*=2)的值都是【标准未规定】的。它们不具有可移植性,研究它们没有任何实际价值!也正是这个原因,所以对这三个加法表达式的测试程序,我都不打算列出,以免误导初学者。

【总结】除了本篇博文前述列出的四种表达式之外,不要编写“运算结果依赖于运算数的计算顺序”的表达式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值