++和--运算

来源:互联网 发布:网络覆盖翻译英文 编辑:程序博客网 时间:2024/04/28 03:15

++C++的自增运算符,作用是使变量自加1--是自减运算符,作用是使变量自减1++--有两种用法,一种是前缀用法,一种是后缀用法。前缀用法如:++i--i ,后缀用法如i++i--,前缀用法跟后缀用法的差别在于前缀时++i的值为完成i1后的值,--i为完成i1后的值。例如:假设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;

}

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

 

有人说,是126。理由是,表达式从左至右开始计算,因为第一个括号内++运算符是后缀用法,i的初值为3,所以,第一个括号的值是3,计算完第一个括号之后,i自加1,变成4,然后计算第二个括号,第二个括号里的++也是后缀用法,所以,值为4,执行完第二个括号后,i再加1,变成5,接下计算第三个括号,第三个括号里的++也是后缀用法,所以,第三个括号的值为5,然后计算第三个括号相加的和,即3+4+5=12。这个理由看起来不错,似乎应当是这样。然而,运行结果却让人大跌眼镜,竟然是96。这是怎么回事呢?说起来也很简单,这是因为很多编译系统规定,在遇到一条计算表达式中同时出现若干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=156。理由我想大家都想明白,我就不多说了。还有人总结了上例的经验,认为,输出结果应该是96。我们来运行一下这个程序,看看谁说得对……

好了,运行结果出来了,不过这不是什么好结果,可能很多人看完会抓狂,结果尽然是神鬼莫测的186。为什么呢?道理跟上例差不多,那就是很编译系统规定,连续多个前缀式++--运算符出现在同一个运算表达式中时,先将变量连续自加或自减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

       运行程序,验证一下,果然,结果就是156

 

       下面在来讨论一下网上很多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;

}

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

 

       很多人可能会说是74,看起来的确像这样。但是,非常遗憾,实验再一次证明,你可能猜错了,结果是84。为什么是84呢?前面说过int i=3cout<< (++i)+(++i) <<endl;的情况,编译系统会先将i连续自加1两次,然后将(++i)一律判定为5进行结算,输出10。这里同理,编译系统现将i自加1,然后再对i+(++i)做运算,(++i)的值判定为4i的值也判定为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 45。我们把代码复制到VC6.0VC2005上编译运行一下,看看结果……

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

原创粉丝点击