(文章使用gcc-4.6.2編譯,本文不嚴謹的討論了y=(++i)+(++i)+(++i)+(++i)表達式求值問題,其實這個討論是沒有意義的,原因參見:
http://www.cnblogs.com/pmer/archive/2013/01/02/2842516.html)
最近看到了一道c語言題目,題目是這樣的:
int x,y,i=3; x=(i++)+(i++); i=3; y=(++i)+(++i);
問x和y的值分別是多少?
答案: x的值很容易看出來,是x=3+3=6,同時i=5。
y呢?在同一個運算表達式中兩次++i后,是4+5還是5+5?正確答案是y=5+5=10,i=5。這里加法運算符左右兩邊都是變量x,所以5+5。
這個題目看似很簡單,其實可以應發聯想,若y的表達式為:
i=3; y=(++i)+(++i)+(++i)+(++i);
這時y的值是多少呢?y=7+7+7+7=28?
正確答案是y=23,i=7。為什么會出現這樣的問題?
不理解這個問題,說明你對c語言運算符的運算規則還沒有透徹的理解。
這里真實的運算規則是:
由於加法運算符“+”是二元運算符,所以每次運算都只需要2個操作數,運算后結果保存在一個緩存變量ans中。
所以先運算(++i)+(++i),則結果為ans=5+5=10,i=5;
然后再運算ans+(++i),則結果為ans=10+6=16,i=6;
然后再運算ans+(++i),則結果為ans=16+7=23,i=7;
然后賦值y=ans=23;
看到這里明白了吧,其實結合逆波蘭表達式的堆棧求解方法很容易理解這個問題。
不要誤以為y=(++i)+(++i)+(++i)+(++i)就是單純運算4次自加后,i和i之間的加法。
同理思考問題:
i=3; y=(i++)+(i++)+(i++)+(i++)
是不是ans=3+3=6;ans=6+5=11;ans=11+6=17;y=17;?
你可以驗證,發現y=3+3+3+3=12;
這說明這里的4個i++是在y的求職結束之后進行自加的。
這個問題怎么理解?和我們前面的結論有沖突?
其實沒有沖突,真實的原因是你要理解i++和++i發生的准確條件:
對於++i,你完全可以用“(i=+1)”來替換,就是說,遇到++i一定是要先進行自加后才會完成其他的運算操作的。
對於i++,這里的自加,准確的講,是整個逆波蘭表達式操作數堆棧中所有的操作數全部清空后,才對需要自加的操作數自加的。簡單的講就是:忽略所有的i++操作符,先進行運算,等表達式的值求解完成后,才對相應的變量進行自加。
