看板 C_and_CPP 關於我們 聯絡資訊
: sum = sub_Function_a ( max ) + sub_Function_b ( max++ ); 借這篇文章,提出我對「Sequence Point」一直以來的疑問,真心跪求知識帝解惑。 之前看這篇文章:http://en.wikipedia.org/wiki/Sequence_point 裡面提到在 C/C++ 的 Sequence Point (順序點) 中,有一個順序點是 「Before a function is entered in a function call.」 在微軟 MSDN 的文章中:http://msdn.microsoft.com/en-us/library/d45c7a5d.aspx 亦指出函數呼叫本身是個順序點。 「Function-call operator. The function-call expression and all arguments to a function, including default arguments, are evaluated and all side effects completed prior to entry to the function.」 又「相加運算子+」的運算優先權高於「指派運算子=」,所以只剩下決定,要先呼叫 sub_Function_a(max) 還是先呼叫 sub_Function_b(max++)。誰先被呼叫,對於結果當然 是有差別的。 但我以為這個部份應該不是未定義的,應該一定是先呼叫 sub_Function_a(max) 吧? 因為看這篇:http://msdn.microsoft.com/en-us/library/yck2zaey.aspx 講解運算優先順序。 該文的圖1 舉「cout << a+b*c << "\n";」做為解說例子。 當 a+b*c 的運算做完,假設是 5566 好了,其運算就變成「cout << 5566 << "\n";」 然後該文章說 「Left shift (<<) has the lowest precedence in the expression, but there are two occurrences. Because the left-shift operator groups left-to-right, the left subexpression is evaluated first and then the right one.」 因為 << 這個二元運算子是左結合性,所以先執行「cout << 5566」,那原文的 sub_Function_a ( max ) + sub_Function_b ( max++ ) 運算,其中 function call 運算子的優先權最高,一定要先執行函數呼叫。又 function call 在 MSDN 也是寫他 結合性為由左到右:http://msdn.microsoft.com/en-us/library/126fe14k.aspx 所以我才認為,應該 sub_Function_a(max) 會先執行,而不是未定義, 但 gcc 是會給警告訊息,而且 wiki 的網頁裡面也說,函數執行順序不一定 「However, it is not specified in which order f(), g(), h() are executed.」 有修過編譯器的課程,但是沒吸收到多少, 求解惑,感謝。 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 124.8.128.171
ericinttu:不知道 max先加一呢? 或是先呼叫 sub function? 10/13 18:14
ericinttu:雖然以下講法很不求長進, 但應該可以把時間花在更值得的 10/13 18:15
ericinttu:事物上. 10/13 18:15
ericinttu:寫程式寫出來就是要確保那段程式是可以重覆被利用的, 而 10/13 18:16
ericinttu:且是依照使用者下達的指令/意圖去完成想要的結果. 10/13 18:17
ericinttu:可是偏偏這個例子只是想省去一行程式碼(我目光淺薄只看 10/13 18:18
ericinttu:到這點), 卻不用更好閱讀更好理解程式的寫法去分別處理 10/13 18:19
ericinttu:這兩次呼叫 sub function. 10/13 18:19
ericinttu:要自虐, 要考驗compiler的能力也就算了. 10/13 18:20
purpose:嗯,會先把max送進堆疊,再把max做++,再呼叫sub function 10/13 18:21
purpose:以保證,所有副作用會在進入函數主題前發生完成。 10/13 18:21
purpose:函數「主體」(body) 10/13 18:21
purpose:很常見的寫法是 result = foo(a) + bar(b); 如果 a,b 是 10/13 18:23
purpose:全域變數,那在 foo 時看得到 b,此時就非得考慮 bar 是否 10/13 18:23
purpose:在 foo 之前有對 a,b 做過改變 10/13 18:24
nowar100:結合順序是多個相加才要討論 你這只有一個加號而已 10/13 18:38
nowar100:與實作相關的部分是哪個先呼叫 不是多個加號時要怎樣結合 10/13 18:39
loveme00835:就算是左結合, 畫遞迴樹出來看, 它們還在同一個LEVEL 10/13 18:43
loveme00835: ↑parsing tree 10/13 18:47
purpose:>10/13 18:38 可是有兩個()運算子,而()運算子也是左結合 10/13 18:57
purpose:遞迴樹我不會,以後有機會看看,謝謝 10/13 18:58
LPH66:但()本身已經有限制求值順序的功能 它是兩個 token 10/13 19:07
LPH66:就算不看parse tree也知道在這裡兩個誰先做並沒有一定 10/13 19:08
LPH66:所以這裡一直都沒有結合性問題 10/13 19:08
LPH66:這裡的兩個()就像(3+4)*(5+6)一樣 3+4和5+6誰先算並沒有一定 10/13 19:09
LPH66:即使(3+4)*(5+6)*(7+8)也一樣 雖然第一個*先算 10/13 19:10
LPH66:但並沒有規定7+8就得在*算完之後才能算 10/13 19:10
purpose:謝謝 LPH66 前輩回答,對我很有幫助,感激不盡。 10/13 19:17
loveme00835:簡單說就是「評估值」跟「計算」的順序是兩碼子事 10/13 19:36
yauhh:左結合是說如果a+b+c就一定要先求a+b再求c 10/13 19:40
yauhh:但是並不代表任何x+y都一定是先去取x值. 10/13 19:41
yauhh:這觀念當初也是受lph66指點過才稍微記得. 10/13 19:41
tinlans:我倒是覺得你編譯器修到 100 分,也未必有學到這東西。 10/13 21:16
tinlans:因為這種東西,實質上不算在 compiler 的課程範圍內。 10/13 21:17
purpose:謝謝各位版友的回應,我以後會好好做人。 10/13 22:16
purpose:編譯器我沒買書,學分又是混到的,所以才有此誤解,謝指正 10/13 22:16