Re: [問題] 什麼情況下會從後往前做運算?

作者: RishYang (Rish)   2019-05-11 13:03:24
前兩樓有提到這個問題與第八誡相關
不過第八誡可能有些不夠清楚
https://reurl.cc/0nZmk
https://reurl.cc/YQ0D4
這兩篇看完就可以解開你心中的疑惑
時間有限,讓我為你簡單整理一下部分內容
先從簡單的四則運算開始
int ans = 1+2+3+4;
ans是10
原因是加法的結合方向(associativity)
加法的結合方向是向左,可得到:
(((1+2)+3)+4)
*下方有結合方向的補充
再來複雜一點的
int ans = 1*2+6/3;
ans是4
因為((1*2)+(6/3))而不是(1*(2+6)/3)
是由於乘法(*)運算子優先權(precedence)較加法(+)高
國小四則運算口號:
先乘除,後加減,括號要先算
根據口號,但是要先算(1*2)還是(6/3)?
兩個括號的結果互相'獨立',其中一個先算不影響答案
1 * 2 = 2不影響後面的(6/3),這就是我指的獨立
回到你問的兩個例子
c = sub1(a,&b)+sub2(&a,b);
是加號左邊先還是右邊先算(先求值)
'先算'涉及求值順序(Order of evaluation)
求值順序沒有'左到右'或'右到左'的順序
printf("%d\n%d\n%d\n%d\n",a+b+c+d,(b*=a),(a+=d),(d++));
a+b+c+d, (b*=a), (a+=d), (d++)
以上四個求值地位相同,不會有哪個求值一定會先做
由於一個向左,一個向右,加上國小口號
讓你誤會存在'執行順序方向',實際上執行順序是假議題
沒有一個執行順序方向,各自表述的空間
是因為你的求值並非'獨立',所以你才被電腦(可能是編譯或是執行時期)誤導
希望你看完,更能體會第八誡字句的含意(以下為第八誡節錄)
當一段程式碼中,某個變數的值用某種方式被改變一次以上,
例如++x/
作者: Schottky (順風相送)   2019-05-11 13:55:00
作者: ohmylove347 (米特巴爾)   2019-05-11 15:45:00
作者: RishYang (Rish)   2019-05-11 16:35:00
編譯器可以檢查Wsequence-point編譯-Wall起來,八誡不會難
作者: cuttheshit (科特落雪)   2019-05-11 16:51:00
感謝大大耐心解惑 雖然還是不太懂 決定先跳過這個點了"以上四個求值地位相同,不會有哪個求值一定會先做"編譯結果那四個參數的取值順序是 4,3,2,1那為何不能是 4,2,3,1呢 不禁有這樣子的疑惑因為第一條式子也是"後面的結果先做有可能改動到前面"的情況 可是卻可以是從左邊開始算若是第二條用"因為後面先做會影響到前面的結果,所以先做後面" 那麼又跟第一條式子矛盾了 主要是卡在這裡原本做題目好好的,自從遇到case2那條奇怪的式子後反而導致往後做時,一直會冒出一個念頭 是不是該後往前有種一知半解最危險的感覺,反而會顧慮太多
作者: art1 (人,原來不是人)   2019-05-11 17:20:00
「不要在一個運算式中,寫出變數會互相影響的程式碼」
作者: RishYang (Rish)   2019-05-11 18:11:00
在這個問題上不用擔心會有一知半解的情形art1所言是整篇重點,沒有這種疑義才是良好的程式碼

Links booklink

Contact Us: admin [ a t ] ucptt.com