C 语言基本概念----再议副作用

C 语言基本概念----副作用icon-default.png?t=M85Bhttp://mp.weixin.qq.com/s?__biz=MzIyNDQyMzQ5Ng==&mid=2247489877&idx=1&sn=3a39a8204f80f475905070858b94d490&chksm=e80e6272df79eb6483e10db9aecfa09c7ee16cde2a974c934b7154e34b28bd888b91e105d6ab&scene=21#wechat_redirect一文中留有2个思考题,其中第一个思考题是:

思考1:上面程序中的表达式 k=++j+i+++j对吗?它是否也存在未定义行为?

我们用程序来验证。

#include <stdio.h>
int main(void)
{
  int i,j,k;
  i=1;
  j=2;
  k=++j+i+++j;
  printf("i=%d, j=%d, k=%d\n",i,j,k);
  return 0;
}

上面这个程序在VC++6.0和Dev C++ 5.11环境下运行的结果都是

但是按照标准来分析该表达式,它仍然存在未定义行为。分析如下:

++j+i+++j等价于(++j)+(i++)+j。

在执行第7行时,整型变量i和j的值分别是1和2。当计算表达式++j+i+++j时,需要计算++j和i++,而这两个子表达式的副作用是修改i和j的值。

假设:

1.把计算子表达式++j的值记为_{V++j},它的副作用是将该值写回j,记为_{S++j}

2.将计算子表达式i++的值记为_{Vi++},副作用记为_{Si++}

3.第一个加运算。将获取+运算符的左操作数记为OPL1,右操作数记为OPR1,将左右操作数进行加操作的值记为_{V+1}

4.第二个加运算。将获取+运算符的左操作数记为OPL2,右操作数记为OPR2,将左右操作数进行加操作的值记为_{V+2}

按照运算符的优先级和结合性,这些事件发生的顺序可能是:

_{V++j}→OPL1_{S++j}→OPR1_{Vi++}_{Si++}_{V+1}→OPL2→OPR2_{V+2}

OPL1=3,_{S++j}=>j=3,OPR1=1, _{Si++}=>i=2, _{V+1}=4, OPL2=_{V+1}=4, OPR2=j=3,_{V+2}=7,

 所以,表达式++j+i+++j的值为7. 

也可能按这样的顺序执行:

_{V++j}→OPL1→OPR1→_{Vi++}_{V+1}→OPL2→OPR2_{V+2}_{S++j}_{Si++};

OPL1=3,OPR1=1, _{V+1}=4, OPL2=_{V+1}=4, OPR2=j=2,_{V+2}=6,_{S++j}=>j=3,_{Si++}=>i=2, 所以,表达式++j+i+++j的值为6。   

通过上面的分析,可以肯定地说,这个表达式存在未定义行为。虽然这个表达式在VC++6.0和Dev C++ 5.11环境下运行结果相同,但仍不能说它是正确的表达式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lhw---9999

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值