求助一个C语言的问题 int i=3; 则k=(i++)+(i++)+(i++);执行过后k的

求助一个C语言的问题
int i=3;
则k=(i++)+(i++)+(i++);执行过后k的值为(),i的值为()
为什么k的值是9呢,我算总是得12。 i值等于6没有异议
第一个i++=3 第二个i++=4 第三个i++=5 加起来就是得12,哪里的问题呢 ?

这个问题给你说了答案,以后你还会遇到很多次这样的问题。

不如直接告诉你原理来得实在。

关于++i,i++的问题看下面看完你再不会,打死我吧!),请认真读完。然后再回来看你这道题。完全就是小儿科。

    ++是C++的自增运算符,作用是使变量自加1;——是自减运算符,作用是使变量自减1.++和——有两种用法,一种是前缀用法,一种是后缀用法。前缀用法如:++i、——i ,后缀用法如i++、i——,前缀用法跟后缀用法的差别在于前缀时++i的值为完成i加1后的值,——i为完成i减1后的值。例如:假设i的初值为3,执行cout<<++i<<endl;输出结果为4,而执行cout<<i++<<endl;输出结果为3.——运算符同理。这是世人皆知的常识,我们不再讨论,现在我们来讨论一点有趣的东西,看如下代码:

 #include <iostream>

using namespace std;

 

int main()

{

int i=3;

cout<<(i++)+(i++)+(i++)<<endl;

cout<<i<<endl;

return 0;

}

   

    问,第一次和第二次输出的结果分别是多少?

    有人说,是12和6.理由是,表达式从左至右开始计算,因为第一个括号内++运算符是后缀用法,i的初值为3,所以,第一个括号的值是3,计算完第一个括号之后,i自加1,变成4,然后计算第二个括号,第二个括号里的++也是后缀用法,所以,值为4,执行完第二个括号后,i再加1,变成5,接下计算第三个括号,第三个括号里的++也是后缀用法,所以,第三个括号的值为5,然后计算第三个括号相加的和,即3+4+5=12.这个理由看起来不错,似乎应当是这样。然而,运行结果却让人大跌眼镜,竟然是9和6.这是怎么回事呢?说起来也很简单,这是因为很多编译系统规定,在遇到一条计算表达式中同时出现若干i++、i——的情况时,在当前语句中并不执行i的自增和自减,i的初值是多少,i++和i——的值就是多少,当这条表达式执行完成之后,再将i连续自加或自减若干次。

    再看如下代码:

 #include <iostream>

using namespace std;

 

int main()

{

int i=3;

cout<<(++i)+(++i)+(++i)<<endl;

cout<<i<<endl;

return 0;

}

   

    问,第一次和第二次输出的结果分别是多少?

    有人说,结果应该是4+5+6=15和6.理由我想大家都想明白,我就不多说了。还有人总结了上例的经验,认为,输出结果应该是9和6.我们来运行一下这个程序,看看谁说得对……

    好了,运行结果出来了,不过这不是什么好结果,可能很多人看完会抓狂,结果尽然是神鬼莫测的18和6.为什么呢?道理跟上例差不多,那就是很编译系统规定,连续多个前缀式++和——运算符出现在同一个运算表达式中时,先将变量连续自加或自减N次,然后判定++i的值为i+N.

    为了验证上面的说法,请看下面的代码:

 #include <iostream>

using namespace std;

 

int main()

{

int i=3;

cout<<(++i)+(i++)+(++i)<<endl;

cout<<i<<endl;

return 0;

}

   

    按照我们上面的推测,第一个输出语句应当是这样执行的:首先,扫描整条运算表达式(++i)+(i++)+(++i),发现有两处++的前缀式用法,于是,将i连续自加两次,然后开始计算表达式,第一个括号是++i,判定为5,第二个括号是i++,判定值为5,第三个括号是++i判定值为5,最后,计算结果5+5+5=15.因为表达式中有一个i++,所以执行计算完之后将i的值再自加1,变为6.

    运行程序,验证一下,果然,结果就是15和6.

    下面在来讨论一下网上很多C++论坛里讨论得很多的int i=3;问++i+++i+i++的值是多少的问题。

    我看到CSDN里也有人在讨论这个问题,很多人在回帖,答案似乎多种多样,有说是12的,有说是18的,更有说是9的,更有一条回帖十分搞笑——“答案是×××,这是很早以前我的一个很牛×的老师教我的解法得出的结果”。我很无语。学过编译原理的人都知道,“++i+++i”这一段根本就无法解析,编译系统从左至右扫描整条语句,先遇到++i,判断出来是一个i的前缀自加运算,然后接着扫描,遇到一个+,+是一个二目运算符,它的左边已经有一个运算数++i了,系统就向右搜索第二个运算数,又遇到一个+,++比+的运算级别要高,这时,编译系统就将两个+看成一个整体来处理,既然是++,编译系统就认定,肯定它的左边或右边有一个变量,编译系统先搜索左边,发现有一个 i,是个变量,于是它就将i和其后的++组合起来,这时问题就发生了,也就是说第一个i被编译系统绑架到它后面的++那里去了,那么i前面的++是个什么东西呢?编译系统是无法搞明白的,它会倒回去重新搜索++前面是否有左值,发现没有,因此它就认为++是一个缺少左值的自增运算符,于是提示提示用户:'++' needs l-value

    我们写个程序验证一下上面的推测:

 #include <iostream>

using namespace std;

 

int main()

{

int i=3;

cout<<++i+++i+i++<<i<<endl;

cout<<i<<endl;

return 0;

}

   

    果然,编译时有一个错误,提示error C2105: '++' needs l-value ,证实了我们的推测。这个问题的讨论使我们得出一个结论:如果一个变量Ni的两侧都有++或——运算符并且Ni左边的表达式不能分解成X+或X-的形式,那么编译就会出错,X是有值变量。结论有点绕口,举例说明吧:

    程序1

 #include <iostream>

using namespace std;

 

int main()

{

int i=3;

cout<<i+++i++<<endl;

cout<<i<<endl;

return 0;

}

   

    程序1说明:表达式i+++i++中第二个i的左右两侧都有++,于是我们看第二个i的左侧,左侧是i+++,可以分解为(i++)+,其中“(i++)”是有值变量,符合X+的形式,因此i+++i++是合法表达式,可以通过编译。

    程序2

 #include <iostream>

using namespace std;

 

int main()

{

int i=3;

cout<<++i+++i<<endl;

cout<<i<<endl;

return 0;

}

   

程序2说明:表达式++i+++i中第一个i的左右两侧都有++,于是我们看第一个i的左侧,左侧是++,不能分解成X+的形式,因此该表达式不合法。编译时会提示:error C2105: '++' needs l-value

    下面,我们再来讨论一下关于i+++i的问题。曾经有人问,表达式i+++i在编译时,编译系统是怎么拆分的?究竟是拆分成(i++)+i呢,还是拆分成i+(++i)。

    这个问题本身的答案很简单,是(i++)+i,不明白的自己去看编译原理。这个问题令人感兴趣之处并不在这里,不知道大家注意到i+(++i)这个表达式有什么奇特的地方没有?假设有如下程序:

 #include <iostream>

using namespace std;

 

int main()

{

int i=3;

cout<<i+(++i)<<endl;

cout<<i<<endl;

return 0;

}

   

    大家可以猜测一下程序的运行结果。

    很多人可能会说是7和4,看起来的确像这样。但是,非常遗憾,实验再一次证明,你可能猜错了,结果是8和4.为什么是8和4呢?前面说过int i=3;cout<< (++i)+(++i) <<endl;的情况,编译系统会先将i连续自加1两次,然后将(++i)一律判定为5进行结算,输出10.这里同理,编译系统现将i自加1,然后再对i+(++i)做运算,(++i)的值判定为4,i的值也判定为4,因此计算结果是8.

    下面我们来讨论int i=3;cout<<i++<<“ and ”<<i++<<endl;的问题。首先请看如下程序,猜测输出结果:

 #include <iostream>

using namespace std;

 

int main()

{

int i=3;

cout<<i++<<" and "<<i++<<endl;

cout<<i<<endl;

return 0;

}

   

    很多人认为输出结果应该是“3 and 4”和5.我们把代码复制到VC6.0或VC2005上编译运行一下,看看结果……

    好了,运行结束,结果是“4 and 3”和5.Oh!My God!Can you tell me why?上帝不会告诉你,我可以告诉你。这是因为很多编译系统在处理输出流时,是从右至左的。在上面的例子中,两处i++处于同一个输出序列中,编译系统会先计算处于右侧的第二个i++,这时i的值为3,因此右侧i++的值为3,之后,i+1变成4,计算第一个i++的值为4,计算完之后将i的值再加1,最后才是输出结果,所以输出结果是4和3.

温馨提示:答案为网友推荐,仅供参考
第1个回答  推荐于2017-09-04
1、i++的意思是运行完算式后再执行i的自加。所以这个可以看作是:k=i+i+i,i++,i++,i++。
2、一次进行计算可以得到,k=9,i=6追问


int i=3;
则k=(i++)+(++i)+(i++);执行过后k的值为(),i的值为()
是不是 i++=3 ++i=4 i++=3 最后k=10?这样好像不对吧

追答

你首先要弄懂++a和a++的问题,虽然这两者都是指a自加,但是在运算中是不同的
1、++a是指先自加后进行运算,举个例子:a=1;b=++a;这里的因为是++a所以运算的顺序是a=a+1,b=a。所以是a=1+1=2,b=2
2、a++是指先自加后进行运算,还是举个例子:a=1;b=a++;这里的因为是a++所以运算的顺序是b=a,a++。所以是a=2,b=1;
3、再看这道题,如果(注意我说的是如果)你按照语法的规定去运算,这里的运算顺序应该是:++i,k=i+i+i,i++,i++。最后结果算出来是k=12,i=6,注意,以为你先把i自加了一次,所以i的值是等于4的。而不是像你那样两个等于3,一个等于4。
4、好了,如果你仔细可以看见我解释的第三个里面有个如果。这个原因是这样的。你把这段代码输入到编译器里面去,你可能会发现答案不是我说的这样,包括你最开始发的那道题的答案。而且你如果用不同的编译器去编译的话,还会发现答案不一样。原因在于不同的编译器对单一变量的多个自加或者自减的判定顺序是不一样的。就拿你的例子举例,它可能会先执行前面两个自加,然后赋值给k后,再执行最后一次自加。也有可能回事其它情况。其实这种题目是没有意义的。正式编译时也不会遇到这样的编译。
ps:最后一段段你能看懂就看,看不算了。当你以后熟悉c后你就能明白

本回答被提问者采纳
第2个回答  2015-07-31
我觉得可以这样理解,i++:先用再加,++i:先加再用,为什么答案是9,因为用i的初值计算,等全部加完之后,再进行i的加加运算追问


int i=3;
则k=(i++)+(++i)+(i++);执行过后k的值为(),i的值为()
是不是 i++=3 ++i=4 i++=3 最后k=10?这样好像不对吧

第3个回答  2015-07-31
三个括号里面结果都是3,是同一优先级的运算,I 的三次赋值,是赋值后带入后面的运算,赋值是成功了,却没有后面后续的运算了!
第4个回答  2018-12-22
这个表达式的执行是未被良好定义的。在不同的编译器里得出的结果不同。例如用gcc编译,会给出结果是12而不是9,探讨这个问题意义不大。
相似回答