4.1.6 操作符之间的优先顺序

在表达一些比较复杂的条件判断时,在同一个表达式中,有时可能会存在多个操作符。比如,我们在判断要不要买某个西瓜时,不仅要判断它的总价(单价8.2元/斤,一共10.3斤)是否小于100块钱(因为兜里只有这么多钱),同时还要判断这个西瓜是否有坏掉的地方。要表达这个复杂的条件判断,我们不得不把前面学过的算术操作符、关系操作符和逻辑操作符全都派上场:

bool bBad = false;   // 是否有坏掉的地方
float fPrice = 8.2;  // 单价
float fWeight = 10.3;    // 重量
// 判断总价是否小于100且是否坏掉
if(fPrice * fWeight < 100 && !bBad)
{cout<<"买西瓜"<<endl;
}
else
{cout<<"算了,不买了"<<endl;
}

在“fPrice * fWeight < 100 && !bBad”这个表达式中,有算术操作符“*”,有关系操作符“<”,同时也还有逻辑操作符“!”和“&&”。那么,这么多操作符在同一个表达式中,到底该从哪一个操作开始呢?这个表达式的最终结果又是什么呢?

要想搞清楚一个表达式是按照什么顺序计算的,就得先搞清楚各个操作符之间的计算优先级。按照正确的计算顺序进行计算,才可以得出正确的结果。在C++中,各个操作符的优先级如表4-1所示。

表4-1  操作符的优先级

级别

操  作  符

说    明

1

( )

括号是所有操作符中的领导,具有最高的优先级。如果括号内部还有括号,内部括号的优先级更高

2

!、+(正号)、-(负号)、++、--

它们都是一元操作符,往往是对操作数进行计算得到结果后继续参与下一个计算

注意,这里的+、-指的是改变数值正负属性的符号,而不是加减操作的符号

3

*、/、%

乘、除、取余运算

4

+、-

加、减运算

5

>、>=、<、<=、==、!=

关系运算

6

&&

逻辑与运算,它会首先计算其左侧表达式的值,当其值为true时,才会继续计算右侧表达式的值,最后计算两个值的逻辑与

7

||

逻辑或运算,它同样会首先计算其左侧表达式的值,若其值为false,则继续计算右侧表达式的值,最后计算两个值的逻辑或

8

=、+=、*=、/=、%=

赋值操作

表达式的计算顺序规则是:总是优先计算优先级较高的操作符;同一优先级的操作符,则按照从左到右的顺序进行计算;如果有特殊规则的操作符(比如逻辑与“&&”),则按照特殊规则进行计算。在清楚了各操作符的优先级及表达式的计算规则后,那就可以计算上面这个复杂表达式的结果了。在这个表达式中,有一个拥有特殊规则的操作符“&&”,按照它的计算规则,这个表达式会首先计算其左侧表达式的值:

fPrice * fWeight < 100  // 首先得到计算的左侧表达式

在这个表达式中,没有特殊规则的操作符,那就按照操作符的优先级进行计算。其中,优先级最高的是计算总价的乘法算术操作符“*”,对其进行计算后得到一个中间结果:

84.46 < 100   // fPrice*fWeight的结果是84.46

这个中间结果表达式只有一个操作符,直接计算得到其结果值为true。按照“&&”操作符的计算规则,如果左侧表达式的值为true,则继续计算其右侧表达式的值。所以,接下来要计算的表达式变为:

true && !bBad     // 左侧表达式计算完成后的中间结果

在“&&”的右侧只有一个操作符“!”,直接计算得到的中间结果是:

true && true

现在,剩下唯一的逻辑与操作符“&&”,最终结果一目了然,对两个true值进行逻辑与运算,表达式的最终结果是true。计算机在对表达式进行计算时,是按照各个操作符的优先级确定的计算顺序进行的。反过来,这也就要求我们在设计表达式的时候,也同样必须遵守操作符的优先顺序,按照这个顺序来设计表达式。否则,实际的计算顺序跟我们设想的计算顺序不同,得到的计算结果自然也就跟我们的设想大相径庭了。从这个意义上讲,熟悉和掌握操作符的优先级十分必要。

最佳实践:合理使用括号标示表达式的计算顺序

从上面这个例子我们可以看到,过于复杂的表达式计算起来非常麻烦。虽然表达式是由计算机负责计算,我们不用担心计算机怕麻烦。但是,表达式却是由程序员进行设计,并且也是要提供给他人阅读的。设计过于复杂的表达式很容易出错,且代码的可读性非常差。所以我们应当尽量避免在同一表达式中混合使用多个操作符,尽量保持表达式的短小精悍。必要的时候,可以将复杂的表达式拆分成多个较小的表达式分别计算得到中间结果,最后再将中间结果组合起来得到最终结果。例如,我们可以把上面的复杂表达式拆分成两个较小的表达式,分别判断是否有坏掉的地方以及总价是否小于100块,然后再将这两个中间结果进行“与”运算,得到最终结果:

// 将复杂表达式拆分成两个较小的表达式
bool bFresh = !bBad;    // 表示是否新鲜
float fTotal = fPrice * fWeight; // 计算总价
bool bMoney = fTotal < 100;  // 判断总价是否小于100块
// 对中间结果进行比较
if( bFresh && bMoney)
// …

经过这样的拆分,每个表达式的计算都清楚明了,减少了出错的可能,可读性也得到了提升。但是它同时也带来一个不便之处,那就是代码变的过于繁琐。既想得到拆分表达式带来的清楚明了的好处,又想避免代码繁琐的不便,那就只有使用“()”了。

“()”的优先级是所有操作符中最高的,使用它,可以人为地按照设计者的意图标示表达式中的计算顺序。比如,可以改写上面的表达式,用括号来表达我们希望的计算顺序,让其表达的意义更加清晰:

// …
if(((fPrice * fWeight) < 100) && (!bBad))
// …

使用括号后,整个表达式的计算顺序变得一目了然:按照括号确定的计算顺序,首先计算最里层的(fPrice * fWeight) 得到中间结果84.46,然后计算(84.46 < 100)得到中间结果true,接着计算(!bBad)得到中间结果true,最后计算“true && true”得到最终结果true。使用括号后,计算顺序跟默认顺序相同,但是却增加了代码的可读性,让我们对计算顺序一目了然,同时也避免了让代码变得过于繁琐。另外,在某些特殊情况下需要改变表达式的默认计算顺序时,括号成为一种必须。

总结起来,使用“()”后,我们想让表达式按照什么顺序计算就按照什么顺序计算,妈妈再也不用担心我记不住各个操作符的优先级。

4.1.7  将表达式组织成语句

学习C++编程,实际上也就是学习如何使用这门特殊的语言来描述和表达现实世界,就如同我们学习英语是为了用它来描述和表达现实世界一样。在前面的章节中,我们学习了操作符,学习了由操作符连接操作数而构成的各种表达式,而这些只能算是这门语言中的“短语”,它们可以表达一定的意义,但却是不完整的:

// 短语式的表达式
a        // 一个单独的变量,什么都不做
3 + 2    // 用算术操作符“+”计算3和2的和

这些表达式可以被执行,但它们并不改变程序的状态,也没有计算结果保留下来,所以没有任何实际的意义。就像在英语中我们需要给短语加上主谓宾才能构成一个完整的句子一样,在C++中,我们也同样需要把一些表达零散意义的表达式组合起来,最后再加一个英文分号表示结束,以此来形成一个语句,用以完成某个相对独立而完整的功能。例如,把上面两个表达式通过赋值操作符组合起来,就形成了一条完整的赋值语句:

// 赋值语句
a = 3 + 2;

形成语句后,它表达了一个完整的意义:用算术操作符“+”计算3和2的和,然后将其赋值给变量a。

在C++中,语句和表达式并没有严格的区分。很多时候,一个表达式加上一个分号就可以直接形成一条语句。语句强调它所完成的功能,而表达式关注它所描述的运算和最终的结果。在此之前,我们已经接触过两种最常见的语句类型:变量定义语句和赋值语句。

知道更多:使用“{}”表示的语句块

当连续的多条语句属于同一个控制结构时,可以用一对花括号“{}”将这些语句括起来,从而形成一个语句块,共同表达一个相对独立的意义。在使用上,语句块与单独的语句并无太大区别,但是它的意义在于,它可以将多条语句打包成一个语句块,从而可以在for循环等控制结构中执行多条语句。例如,在for循环结构中,我们可以这样来统计从1到100间所有整数的和:

int nTotal = 0;for(int i = 1; i <= 100; ++i)nTotal += i;

这个统计只需要一条语句就可以完成,自然可以把这条语句直接放在for循环结构之后完成,可是如果我们只需要统计这个区间中所有偶数的和,那么就需要加上条件判断,这就不是单独一条语句可以完成的了。我们必须用“{}”将所有判断偶数、统计偶数的语句打包成一个语句块,然后放在for循环结构之后才能完成统计:

for(int i = 1; i <= 100; ++i){ // for循环语句块开始if(0 == i%2) // 判断语句nTotal += i; // 统计语句
} // for循环语句块结束

除了打包语句之外,语句块的另外一个意义是,它代表了C++中的作用域的起讫位置。关于作用域的具体介绍可以参考后继的7.3.3小节。

转载于:https://www.cnblogs.com/nihaoCPP/p/4085033.html

你好,C++(18) 到底要不要买这个西瓜?4.1.6 操作符之间的优先顺序相关推荐

  1. android 8三星note8,去年发布的三星Note8到底还值不值得买,三星Note8深度体验!!!...

    去年发布的三星Note8到底还值不值得买,三星Note8深度体验!!! 2019-01-27 16:24:56 20点赞 17收藏 18评论 大家好我是没有钱谈恋爱,只能在SMZDM上写文章赚金币的小 ...

  2. 激活策略 查询_苹果手机未激活也可能不是原装货,激活过的手机到底能不能买?...

    苹果手机未激活也可能不是原装货,激活过的手机到底能不能买? 去年,苹果手机销量下滑的事实大家已经看在了眼里,很多业内人士分析,造成苹果手机销量下滑的主要原因是创新度太低,还有就是售价太高.虽然苹果手机 ...

  3. 网吧能做计算机试题么,网吧二手电脑到底能不能买?答案真是令人很意外

    在我们生活中,经常会有网吧将更换下来的电脑进行转卖.有的小伙伴觉得网吧的电脑只是用来打游戏,损耗没有那么大,所以完全可以买回来.事实真的是这样的吗?网吧的二手电脑到底能不能买呢? 首先,如果你想买网吧 ...

  4. android平板触控笔,产品轻体验系列 篇一:买平板到底要不要买配件?华为MatePad10.8磁吸键盘/触控笔体验...

    产品轻体验系列 篇一:买平板到底要不要买配件?华为MatePad10.8磁吸键盘/触控笔体验 2020-08-26 17:36:44 12点赞 19收藏 16评论 创作立场声明:很多小伙伴在购买平板之 ...

  5. 计算机专业游戏本后悔,毕业了,到底要不要买游戏笔记本电脑?好多人买了都后悔了?...

    小编今天看到一个新闻,高考过后很多人带着被子组队去网吧通宵玩游戏,年轻真的就是好啊,紧张辛苦这么久,终于可以放肆一下了,但是总是去网吧不是一个长久之计啊,很多人就想着买一个游戏笔记本吧,预算大概是50 ...

  6. 到底买苹果XS还是XR_没有5G的苹果到底还值不值得买

    盼星星盼月亮,果粉们终于盼来了iphone 11, 小编是忠实的华为粉,支持国产华为,所以无感. 那没有5G的iPhone,到底值不值得花钱去买? 我们先来看看这张参数表 其实参数表和价格已经给我们了 ...

  7. 机械键盘到底要不要买?秒懂!

    点击上方"中兴开发者社区",关注我们 每天读一篇一线开发者原创好文 本文转自ZOL 键盘是电脑外设当中最重要的部件之一,二三十年前,电脑刚刚开始普及的时候.机械键盘是绝对的主流,直 ...

  8. html5测试评分iphone8,到底要不要买iPhone8_看完这8个理由你就不纠结了-太平洋IT百科...

    iPhone8和iPhoneX的同时发布打破了苹果以往遵循的tick-tock法则,两步并一步走,尴尬了iPhone8,也尴尬了想要换机的消费者.iPhone8和前代相比,外观变化不大,实际感受上也没 ...

  9. 计算机不买游戏本可以吗,都8102年了还虚假宣传?这种游戏本到底能不能买

    [PConline 杂谈]对于现在的游戏玩家来说,更多人会选择买一台游戏本而不是买一台台式机,虽然台式机的游戏体验会更好,但对于生活节奏如此之快的现在来说,能够轻松移动的游戏本似乎是更好的选择. 而如 ...

最新文章

  1. Dask.distributed创建client时出现报错
  2. wince对中文字体的支持
  3. JSP中动态includ与静态includ的区别
  4. CentOs基础操作指令(文件所属管理和权限管理)
  5. K3/Cloud点按钮打开单据,列表,动态表单,简单账表和直接Sql报表示例
  6. Python DearPyGui 常用控件一
  7. teamviewer解除5分钟商业限制最新方法,永久解决商业限制问题,无需一直改MAC地址
  8. 《SolidWorks 2017中文版机械设计从入门到精通)》——2.7 复合草图实例操作
  9. 发现eclipse红叉,查看markers发现Target runtime Apache Tomcat 6.0 is not defined
  10. 黑鹰安全网_育鹰计划_笔记
  11. Laya位图字体制作
  12. 在微信公众号中html5页面跳转页面,微信公众号自定义菜单如何将点击动作换成跳转到网页...
  13. java英文翻译_Java实现英文文本单词翻译器功能的简单实例
  14. 木子-数据库-oracle如何创建一个新的实例
  15. SendCloud从注册到邮件发送使用心得
  16. 暂存更改 切换分支 git
  17. webservice接口等待时间_调用webservice超时问题的解决
  18. Android 自定义控件之——画个老虎机来玩玩
  19. 常见的希腊字母及读音
  20. 全国各地DNS地址详细列表

热门文章

  1. MySQL的优化(大纲)
  2. class() 高级用法 -- lua
  3. 传清华应届生获Facebook offer
  4. 10分钟快速配置sublime2支持jQuery开发
  5. C++对象内存布局--①测试虚函数表属于类
  6. 3D模型在网页上显示
  7. 互联网协议 — IP 网络的 QoS 服务模型
  8. 如何实现分享链接到微信朋友圈时显示自定义LOGO以及名称介绍
  9. 编写测试用例的常用方法
  10. 聊聊reactive streams的schedulers