c++ - C语言 关于b=a+++a++运算问题?
阿神
阿神 2017-04-17 14:00:29
0
17
2789

篇幅有点长,让您受累了。。。

a++这个问题一直很困扰,自己做了个测试,虽然都知道a++是先使用

a再进行自加,疑问点就是这个a使用的期限是什么时候结束?一开始以为是表达式代码行完成后,在第二行代码需要试用a时,就是自加结果,这也是最常用的情况,也很好理解,如:

int a=0,b;
b=a++;
printf("a=%d b=%d",a,b);//输出:a=1,b=0

那假如在同一行表达式中出现2次a++,也就是说a++后又与其他变量进行运算,如下代码:

int a=10,b=0;
b=a+++a++;
printf("a=%d b=%d",a,b);//输出a=12 b=21

如果上面的理论成立那b应该等于20,根据执行结果显然不成立,所以我觉得应该是当执行a++运算时,a还是10,但当a在与其他变量继续运算时a就已经完成了自增,就是自增后的值与其他变量运算了,在变下代码再测试:

int a=10,b=0;
b=a+++b;//b=10(因为a++优先级大于++b,所以直观点应该是b=(a++)+b,尽管此时括号是多余的)

显然这种说法也不成立。

对b=a+++a++运算的猜测步骤为:

  1. 第一个a++ //此时a=10

  2. 第二个a++ //因为第一步运算完后a自增1,所以此时a=11,是第一个a++运算后的值

  3. b=a+a //b=11+11=22,这点就不理解了,之所以最终结果这个b=21,难道是b=10+11吗,但中间+号的表达式两端都是a,应该两端的值都是一样的啊,应是22或20啊,怎么会是21,b=(a++)+(++a) 这个结果为22,应该可以说明+号两边都是a的话,第一个表达式a++中a会被++a后的值覆盖,所以b=11+11。

求解释b=a++a++的详细运算步骤,为啥会是b=21?

还有个问题:

int i=1;
int j=0;
for(;j<5;j++){
     i=i++;
     printf("i=%d",i);
}
printf("i=%d",i);

为什么i=1?为什么i=i++执行完后,在执行j<5之前或在下一轮执行前i没有自加?及时for循环中i=1,那for循环执行完后i应该至少会加1吧,起码i也得等于2啊?

阿神
阿神

闭关修行中......

全部回覆(17)
Ty80

我以前學的時候也糾結過這些文法特性。 其實這個連起來寫, 標準裡面也沒有定義要怎麼樣執行。
所以具體的結果依賴編譯器。 所以如果編譯器不同, 具體的結果也可能不同。
所以實際上要避免這種寫法, 避免出現坑爹的錯誤。

阿神

這類程式碼可以幫助我們理解c語言的一些規則,但是在實際工程裡面最好不要出現這種寫法,因為也許過了幾個月你回頭維護程式碼看到這裡會覺得很困惑,或者別人維護你的程式碼更是有想掐死你的心情。好了,說說a+++a++吧,編譯器編譯的時候有個規則叫做貪心法,一次讀入盡可能多的符號,那麼開始可以一直讀到a++,所以這個可以得出是(a++) +(a++),然而我用gcc4.5.1得到的結果卻是20,可以看出來不同編譯器編譯結果是不同的,也許有優化吧。所以,再次重申,這種程式碼不要寫到實際工程裡面!能寫一手整潔明了的程式碼才是優秀的程式猿。

阿神

我就是上文提到的連結的作者。
同時把當時分析時的圖片也引過來一看便知:
反彙編程式碼在這裡:

當然,這是vc++下,g++ ,clang的編譯結果與此不同。
同時,還有先前另外回覆的java和c++的運算順序問題也供參考:
這個問題和運算子沒有關係,都是從右往左計算,而是編譯器對值類型的處理結果不一致導致的差異。
對於gc類語言來說,包括(java,c#,php,javascript)等,對於單句指令的中間運算結果會進行快取。而C/C++由於直接編譯為組譯指令,沒有虛擬機器或引擎的支持,所以不會有這一步。
通俗點來說,對於c++:

a=3*3;//9
a=a+a;//18
a=a-a;//0

也就是說a的值是值型,會隨時跟著a的變化而更新。無論初始設定a的值為幾,結果都是0。 (a-a).
然而對於其他語言,虛擬機器或引擎會自動保存每一步的計算結果。

int a=3;
int result=0;
result=a*a;//9
result=a+result;//3+9=12
result=a-result;//3-12=-9

以上。
引申:PHP 一個詭異的加法演算法的研究

小葫芦

雖然有這樣的語法,但是這就相當於編程中的文言文,只會增加閱讀程序的困難,實際項目中如果寫這種代碼肯定會挨批的

Ty80

感覺像樓上說的一樣, 完全是看 各大編譯器的心情...

刘奇

很多年前我記得TC2.0與VC6對此的處理方式不一樣,所以不用糾結。

其次,在正式專案裡,也是不允許這麼寫的。

大家讲道理

摘自 裘宗燕教授的的文章,應該是中文版最清晰的解釋了。 http://www.math.pku.edu.cn/teachers/qiuzy/technotes/expression2009.pdf 樓上最佳答案從實現原理解釋了結果,但如裘宗燕教授所指出,這個問題是規範層面的。不只是這類程式碼難以理解不要在專案中寫,而是按照歸範定義不能寫。

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板