C基础-表达式求值

本文探讨了C/C++中表达式的副作用和求值顺序对结果的影响,强调了顺序点的重要性。顺序点是副作用最晚生效的时刻,如在完整表达式结束、特定运算符后或函数调用前。例如,表达式`b=a+++a`的结果依赖于副作用的执行时机。同时,求值顺序在涉及副作用的参数计算时尤为关键,Java则明确规定从左到右求值。了解这些概念有助于避免程序中的不确定性和错误。
摘要由CSDN通过智能技术生成

前提

表达式有由2种功能:

  • 表达式会产生一个结果
  • 表达式可能产生一个“副作用”(side effect)
    • 比如i++,返回值是i,产生的副作用是增加1
    • 比如++i,返回值是i+1,副作用也是i增加1

表达式的副作用何时生效,以及运算对象的求值顺序,会影响表达式的值。比如:

int a=4,b;
b = a++ + a

上面的语句cppcheck会给出以下错误提示:
在这里插入图片描述
表达式的结果取决于副作用产生的顺序

  • 如果“+”的两个对象从左往右计算
    • a++的副作用在计算第二个操作数a时已经生效那么计算值是9
    • 如果a++的副作用在进入到"+"运算时,才生效,那么b的值是8
  • 如果"+"的两个对象从右往左计算:
    • b的值都是8

因此下面讲2个概念

  • 顺序点
  • 求职顺序

顺序点

在C、C++等允许表达式有副作用的语言中,通常都规定了顺序点,顺序点就是表达式中的副作用的最晚生效时刻。在程序执行中,存在一系列的顺序点,一旦执行到一个顺序点,此前的副作用都必须生效。但是在顺序点之间并没有任何保证。

C/C++明确定义了顺序点的概念。顺序点位于:

  • 每个完整表达式结束时。完整表达式包括变量初始化表达式,表达式语句,return语句的表达式,以及条件、循环和switch语句的控制表达式(for头部有三个控制表达式)
  • 运算符 &&、||、?: 和逗号运算符的第一个运算对象计算之后
  • 函数调用中对所有实际参数和函数名表达式(需要调用的函数也可能通过表达式描述)的求值完成之后(进入函数体之前)

假设时刻ti和ti+1是前后相继的两个顺序点,到了ti+1,必须实现ti之后发生的所有副作用。当然也可以不等到时刻ti+1,完全可以选择在时段 [ti, ti+1] 之间的任何时刻实现在此期间出现的副作用。

求值顺序

(a + b) * (c + d)
“*”的两个运算对象哪个先算?
fun(a++, b, a+5)
fun及其三个参数按什么顺序计算?
对第一个表达式,采用任何计算顺序都没关系,因为其中的子表达式都是引用透明的。
第二个例子里的实参表达式出现了副作用,计算顺序就非常重要了。在计算第二个表达式时,首先按照某种顺序算fun、a++、b和a+5,之后是顺序点,而后进入函数执行。
Java明确规定求值顺序是从左到右。

参考来源:
http://blog.timd.cn/evaluation-order/

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值