作者RishYang (Rish)
看板C_and_CPP
標題Re: [問題] 什麼情況下會從後往前做運算?
時間Sat May 11 13:03:24 2019
前兩樓有提到這個問題與第八誡相關
不過第八誡可能有些不夠清楚
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/--x/x++/x--/function(&x)(能改變x的函式)
- 如果Standard沒有特別去定義某段敘述中哪個部份必須被先執行,
那結果會是undefined behavior(結果未知)。
- 如果Standard有特別去定義執行順序,那結果就根據執行順序決定。
個人臆測:
不定義執行順序是為了保持與數學運算邏輯的相容性
讓C語言優雅又好入門的方法
其實把敘述一行行寫出來,並不會遜於用一行完成
追求程式邏輯清晰比短小可能來的重要
*結合方向
http://codepad.org/hR8UFMOb
我想這個例子應該可以說明,乘除法向左結合的特性
結合方向遇上非獨立的求值還是會有問題的
最後送給原Po: '凡物皆數'----畢達哥拉斯
C語言裡大家都是傳值,不要分這麼細
很少發文,請鞭小力一點
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 36.237.199.112
※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1557551006.A.060.html
推 Schottky: 推 05/11 13:55
推 ohmylove347: 推 05/11 15:45
→ RishYang: 編譯器可以檢查Wsequence-point 05/11 16:35
→ RishYang: 編譯-Wall起來,八誡不會難 05/11 16:38
推 cuttheshit: 感謝大大耐心解惑 雖然還是不太懂 決定先跳過這個點了 05/11 16:51
→ cuttheshit: "以上四個求值地位相同,不會有哪個求值一定會先做" 05/11 16:53
→ cuttheshit: 編譯結果那四個參數的取值順序是 4,3,2,1 05/11 16:54
→ cuttheshit: 那為何不能是 4,2,3,1呢 不禁有這樣子的疑惑 05/11 16:54
→ cuttheshit: 因為第一條式子也是"後面的結果先做有可能改動到前面" 05/11 16:56
→ cuttheshit: 的情況 可是卻可以是從左邊開始算 05/11 16:56
推 cuttheshit: 若是第二條用"因為後面先做會影響到前面的結果,所以先 05/11 17:00
→ cuttheshit: 做後面" 那麼又跟第一條式子矛盾了 主要是卡在這裡 05/11 17:01
推 cuttheshit: 原本做題目好好的,自從遇到case2那條奇怪的式子後 05/11 17:06
→ cuttheshit: 反而導致往後做時,一直會冒出一個念頭 是不是該後往前 05/11 17:07
→ cuttheshit: 有種一知半解最危險的感覺,反而會顧慮太多 05/11 17:09
推 art1: 「不要在一個運算式中,寫出變數會互相影響的程式碼」 05/11 17:20
→ RishYang: 在這個問題上不用擔心會有一知半解的情形 05/11 18:11
→ RishYang: art1所言是整篇重點,沒有這種疑義才是良好的程式碼 05/11 18:18