| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 4717 人关注过本帖, 4 人收藏
标题:关于i++及++i等问题的详细解释,初学朋友请进。
取消只看楼主 加入收藏
lz1091914999
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:四川
等 级:贵宾
威 望:37
帖 子:2011
专家分:5959
注 册:2010-11-1
结帖率:94.64%
收藏(4)
已结贴  问题点数:100 回复次数:2 
关于i++及++i等问题的详细解释,初学朋友请进。
很多朋友在问,比如:
i = 1;
printf("%d %d", i++, ++i);
输出什么?
int i = 5, j = 2, p, q;
p = (i++)+(i++)+(i++);
q = (++j)+(++j)+(++j);
p、q、i、j的值分别是多少?
以及它们之间的运算顺序等,今天我就来仔细的讲一下。

预备知识
副作用和透明引用:
什么是副作用?专业一点的解释就是一个表达式修改了环境(环境就是其它可修改的数据,如变量),不仅计算值还做了额外的事情。比如表达式:i++,这个表达式就有副作用,因为它修改了环境(i)。还有:
i++ + ++i, j + (i = 3) + k, --i, i-- ...等。
什么是透明引用呢?即不对环境有影响,比如表达式:(a+b)-(c+d),a、b、c、d在这个表达式中都被透明引用了,因为不管先计算哪一边,这个表达式的结果都不变。

第一个问题:
i = 1;
printf("%d %d", i++, ++i);
这里有一个参数列表的计算顺序,到底是++i,i++还是i++,++i? 有人说参数都是从右住左入栈的,所以是++i,i++,假定是这样的顺序,那么应该输出:2 2
如果是从左住右呢?那么输出:1 3 在gcc 4.4.0下输出: 2 3。是不是感到结果很惊讶,难道它有其它的求值顺序?

这里有一个顺序点的概念,什么是顺序点?比如:
i++ + ... + *p;
假定p指向i。表达式i++是一个有副作用的表达式,我们假定这个表达式的计算顺序是从左往右,那么i++肯定先算,当算到*p的时候,之前i++的副作用是否体现到了内存里面?也就是说是否把新值写到了i对应的内存里面?因为i的值是存放在CPU的寄存器里面的,所以如果编译器没有把新值从CPU写到内存里面,那么*p引用到的将是原来的值。如果已经体现了副作用,那么i++和*p之间就有一个顺序点,也就是体现副作用的地方,在下一个顺序点之前所有的副作用都必须实现,即写入内存。

回到上面i++,++i的问题,如果i++和++i之间有一个顺序点,并且计算顺序也知道,是不是就可以推算出结果呢?确实是这样,比如在Java里就可以推算出结果,因为Java规定表达式的计算顺序从左往右,并且所有副作用都会在下一个计算之前实现。

那么在C\C++里答案是什么呢?答案就是不知道!,虽然这样回答有点水,不过确实不知道,如果有人说知道,那么它肯定是专家。

每个编译器都有自己的求值顺序,以及顺序点的规定,但是请放心,一条语句执行完毕之后,这条语句中的所有副作用都会实现,也就是说:
i = 1;
printf("%d %d", i++, ++i);
当printf这行执行之后i的值肯定是3。

所以我觉得上面p和q的问题也没必要解释了,在C\C++里,如果一个表达式中要引用一个变量多次,就不应该对该变量做有副作用的运算,只能是透明引用,否则无法推算出结果来,不同的编译器有自己的求值顺序及顺序点的规定,这都是C\C++允许的。C\C++没有规定这些是为了效率考虑,如果像Java那样规定顺序及副作用的体现,必定会有大量的内存访问,所以Java是牺牲了效率而带来了程序的清晰,稳定。但C\C++依然是高效的语言。当然这些问题只需要注意就行了。也希望初学朋友别在问这些问题了。

关于其它的副作用表达式:i += 1, i += 2, i -= 1, i -= 2, i = 1 等副作用表达式,如果在一个表达式中引用多次,结果依然是无法推测的,i += 1 和 ++i有什么区别呢?比如这段代码:
int a = 1;
printf("%d %d", a += 1, a = 3);
gcc 4.4.0下输出:4 4
结果任然是出乎意料的。

当你遇到这样问题的时候,请直接回答不知道!

[ 本帖最后由 lz1091914999 于 2013-1-11 11:57 编辑 ]
搜索更多相关主题的帖子: 知识 表达式 副作用 
2013-01-07 18:28
lz1091914999
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:四川
等 级:贵宾
威 望:37
帖 子:2011
专家分:5959
注 册:2010-11-1
收藏
得分:0 
利用一下版主的特权,不过这个问题到现在还有人问,确实挺烦的。

My life is brilliant
2013-01-07 18:30
lz1091914999
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:四川
等 级:贵宾
威 望:37
帖 子:2011
专家分:5959
注 册:2010-11-1
收藏
得分:0 
回复 3楼 zklhp
应该两种都可以吧?

写这篇文章也是因为看到了有人问这样的问题,并且还有人在专门研究这些东西,说他发现了什么规律,有些书上也在说表达式是先计算左边还是右边,看了很蛋疼。毕竟是些没必要争论的问题。

My life is brilliant
2013-01-07 18:40
快速回复:关于i++及++i等问题的详细解释,初学朋友请进。
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.025350 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved