c++中的优先级、结合律和求值顺序☆(处理复合表达式)

以下是优先级和结合律在复合表达式中的关系:

复合表达式(compound expression):
是指含有两个或多个运算符的表达式。求复合表达式的值需要首先将运算符和运算对象合理地组合在一起,优先级与结合律决定了运算对
象组合的方式
。也就是说,它们决定了表达式中每个运算符对应的运算对象来自表达式的哪一部分。表达式中的括号无视上述规则不确定优先级时加括号是一个好办法),程序员可以使用括号将表达式的某个局部括起来使其得到优先运算。

一般来说,表达式最终的值依赖于其子表达式的组合方式。高优先级运算 符的运算对象要比低优先级运算符的运算对象更为紧密地组合在一起。
··如果优先级相同,则其组合规则由结合律确定
算术运算符满足左结合律,意味着如果运算符的优先级相同,将按照从左向右的顺序组合运算对象: (这点和数学是相同的
(末尾附:优先级和结合律表)
比如

在这里插入图片描述


求值顺序☆

优先级规定了运算对象的组合方式但是没有说明运算对象按照什么顺序求值。在大多数情况下,不会明确指定求值的顺序。对于如下的表达式

int i=f1()*f2(); //(1)
cout<<i<<" "<<++i<<endl;//(2)

我们知道f1和f2一定会在执行乘法之前被调用,因为毕竟相乘的是这两个函数的返回值。但是我们无法知道到底f1在f2之前调用还是f2在f1之前调用。
为什么会这样?因为c++没有对* 运算符没有明确规定以及如何对运算对象求值,即不知道先求左边的值还是右边的值.
<<运算符也一样,因此在(2)中可能输出0 1 或者1 1这全看编译器选择。因此,这会很容易出错。
可以用以下要求来减少出错的机会:
1.拿不准的时候最好用括号来强制让表达式的组合关系符合程序逻辑的要求。(分不清优先级or 结合律)
2.如果改变了某个运算对象的值,在表达式的其他地方不要再使用这个运算对象。
(求值顺序未定义时但是* ++p,由于++优先级高会先求值,所以不会产出未定义的错误。)

-----既然有未定义求值顺序的,自然也有定义了的:
有4种运算符明确规定了运算对象的求值顺序。
1.逻辑与(&&)运算符,它规定先求左侧运算对象的值,只有当左侧运算对象的值为真才继续求右侧运算对象的值
2. 逻辑或(||)运算符,它规定先求左侧运算对象的值**,当且仅当左侧运算对象为时才对右侧运算对象求值
3. 条件(?:)运算符,诸如(cond?expr1:expr2),条件运算符的执行过程是:首先求cond的值,如果条件为exprl求值并返回该值*,否则对expr2求值并返回该值
4. 逗号(,)运算符,对于逗号运算符来说,首先对左侧的表达式求值然后将求值结果丢弃掉。逗号运算符真正的结果是右侧表达式的值



优先级、结合律、求值顺序的关系

运算对象的求值顺序与优先级和结合律无关,在一条形如f()+g()*h()+j() 的表达式中:
●优先级规定,g()的返回值和h()的返回值相乘
●结合律规定,f()的返回值先与g()和h()的乘积相加,所得结果再与j ()的返回值相加
●对于这些函数的调用顺序没有明确规定。

总结:
1.尽量积累多常用的结合律和优先级规则,不确定的便括号

大多数运算符并不明确规定运算对象的求值顺序:编译器有权自由选择先对左侧运算对象求值还是先对右侧运算对象求值。一般来说,运算对象的求值顺序对表达式的最终结果没有影响。但是,如果两个运算对象指向同一个对象而且其中一个改变了对象的值,就会导致程序出现不易发现的严重缺陷。

在这里插入图片描述

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值