本篇文章主要讲解C++中的i++和++i的运算规则,原本,我以为自己已经掌握了这个知识点,但是,在接触了类似(i++)+(++i)+(i++)的非规范运算时,却卡了很长时间,下面我就来着重讲解这个"事故"。
一.i++与++i的区别
1.i++
i++的意思是先赋值再自增,通俗讲就是计算i++,先计算i,计算结束后i自增1。注意,自增的i不参与开始计算。在进行下一步计算时,自增的i为最新的i。
通过一个示例大家就能明白了。
int main(){
int i=0;
int j=i++;
cout<<"j的值为:"<<j<<endl;
cout<<"i的值为:"<<i<<endl;
return 0;
}
结果:
我们来分析一下:
1).首先i=0。
2).j=i++,根据先赋值后自增原则,先j=i;后i=i+1。
3).结果为:j=0.i=0+1=1。
刚刚也说了,自增的值不参与开始的计算,在后面的计算,自增后的值为最新的值。
再来举个例子:
int main(){
int i=0;
int j=i++;
cout<<"j的值为:"<<j<<endl;
cout<<"i的值为:"<<i<<endl;
int k=i++;
cout<<"k的值为:"<<k<<endl;
cout<<"i的值为:"<<i<<endl;
return 0;
}
结果:
分析:此例子就利用了i自增后的值作为新值计算,步骤:
1).i=0;j=i++;
2).j=i=0,i=i+1=1,此时j=0,i=1(i自增的值)。
3).k=i++,k=i=1(此时的i为自增后的值为1),i=i+1=2。结果k=1,i=2。
2.++i
和i++不同的是,++i是自增后赋值。通俗讲就是计算++i时,先计算i+1,然后将此值赋给i。
还是通过一个例子:
int main(){
int i=0;
int j=++i;
cout<<"j的值为:"<<j<<endl;
cout<<"i的值为:"<<i<<endl;
int k=++i;
cout<<"k的值为:"<<k<<endl;
cout<<"i的值为:"<<i<<endl;
return 0;
}
结果:
分析:
1).i=0,j=++i,此时按照先自增后赋值原则,i=i+1=1(j=i+1=1),i=i(将自增的i赋值给i),所以此时j=1,i=1。
2).k=++i,此时i为1,i=i+1=2(k=i+1=2),i=i(将自增的i赋值给i,此时自增的i为2),所以k=2,i=2。
二.i++与++i的混合运算----(i++)+(++i)或(i++)+(i++)
前面已经讲解了i++和++i的区别,大家也理解了计算规则,可能很多人认为组合计算很简单,但事实是否是这样的呢?
先看i++和i++的混合运算示例:
int main(){
int i=0;
int j=(i++)+(i++);
cout<<"j的值为:"<<j<<endl;
cout<<"i的值为:"<<i<<endl;
return 0;
}
按照正常的分析思路:
1).i=0,j=(i++)+(i++)分开计算:i++先赋值为0,之后自增i=i+1=1。
2).第二个i++,先赋值为1,后自增i=i+1=2。
3).所以j=0+1=1,i=2
但结果是这样的吗?
通过运行程序发现竟然不一致:
再看下i++和++i的混合运算示例:
int main(){
int i=0;
int j=(i++)+(++i);
cout<<"j的值为:"<<j<<endl;
cout<<"i的值为:"<<i<<endl;
return 0;
}
按照正常思路为
1).i=0,先计算i++,赋值0,后i自增为i=i+1=1。
2).计算++i,i=i+1=2,i=i=2。
3).j=0+2=2,i=2。
运算结果:
发现一致,这就很奇怪,经过查阅资料发现:
C语言创始人明确指出:
自增与自减运算只能作用于变量,类似于(i+j)++是非法的,因为自增运算包含了赋值运算,而表达式不能作为赋值运算的左值。
表达式不能作为赋值运算的左值这句是什么意思呢?
举个例子:
int main(){
int j=0;
int k=1;
k++=j;
cout<<"j的值为:"<<j<<endl;
cout<<"k的值为:"<<k<<endl;
return 0;
}
结果出错:
因为k++运算结果是一个临时变量,且这个临时变量并不是程序中定义的可寻址变量的引用,不能被更改,所以不能作为左值表达式,总结就是,左值就是具有存放数据的空间。
而为什么(i+j)++是非法的呢?
假设 int x=(i+j)++;那么它会进行什么操作呢?
x=i+j,i+j=(i+j)+1,很显然表达式作为了赋值运算的左值,这是错误的。
所以,在这里(i++)+(i++)也是非法的,因为在前一个i++的作用下,后面的i就已经是表达式了,表达式不能再做++操作
后面的i是在前面的i=i+1后得到的,也就是说i+1不能再做++操作,因此(i++)+(i++)也是非法的。
那么。非法的表达式是否可以计算呢?
答案是可以的。
编译器在无法做出正确计算步骤的情况下,会采取以下计算格式:
1).先将所有的i++改成i,然后在整个语句的最后添加i的自增次数(语句有几个i++,就自增几次)。
2).先将左边前两项相加,如果前两项中含有++i,则先算++i。
3).前两项的和作为一项,与第三项相加,以此类推。
那么,将以上的(i++)+(i++)来分析,步骤为:
j=i+i;i++;i++
j=0,i=2
将以上的(i++)+(++i)来分析,步骤为:
i+(++i);i++;
j=(++i)+i;//先计算++i
i=i+1=1,i=i=1,j=1+1=2,i自增1为2。
综上:(i++)+(++i)我们的思路结果确实是碰巧和计算机结果一样
不同的是,我们的思路是0+2,而计算机的是1+1。