C++中的i++和++i你真的理解嗎?

菠蘿印象威發表於2020-12-08

本篇文章主要講解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。

看完本篇文章,你會對i++和++i有更深刻的認識。

相關文章