在C 语言基本概念----副作用http://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
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的值记为,它的副作用是将该值写回j,记为;
2.将计算子表达式i++的值记为,副作用记为;
3.第一个加运算。将获取+运算符的左操作数记为OPL1,右操作数记为OPR1,将左右操作数进行加操作的值记为;
4.第二个加运算。将获取+运算符的左操作数记为OPL2,右操作数记为OPR2,将左右操作数进行加操作的值记为。
按照运算符的优先级和结合性,这些事件发生的顺序可能是:
→OPL1→→OPR1→→→→OPL2→OPR2→;
OPL1=3,=>j=3,OPR1=1, =>i=2, =4, OPL2==4, OPR2=j=3,=7,
所以,表达式++j+i+++j的值为7.
也可能按这样的顺序执行:
→OPL1→OPR1→→→OPL2→OPR2→→→;
OPL1=3,OPR1=1, =4, OPL2==4, OPR2=j=2,=6,=>j=3,=>i=2, 所以,表达式++j+i+++j的值为6。
通过上面的分析,可以肯定地说,这个表达式存在未定义行为。虽然这个表达式在VC++6.0和Dev C++ 5.11环境下运行结果相同,但仍不能说它是正确的表达式。