[英]How does Operator Precedence affect Order of evaluation?
我想問一下運算符優先級如何影響評估順序,而不是它們之間的區別。 為了更好地說明我的問題,我將在下面簡要說明運算符優先級。
以下代碼僅用於演示目的。 考慮:
int i=++a*b+c/d/e
有些解釋會說,因為運算符優先級,*和/會在+之前執行,但我喜歡這樣想:如果兩個優先級不同的運算符爭奪同一個表達式,優先級較高的那個得到表達式和 forms 是一個新的表達式及其操作數。 因此,最上面的例子實際上是:
int i=((++a)*b)+((c/d)/e)
這在編譯時是已知的。 在運行時評估順序開始,它決定是a,b,c,d or i
首先得到評估。 哪個表達式首先被評估是由排序決定的,盡管大多數運算符是未排序的或不確定排序的。
C++ 未排序運算符而不是嚴格的從左到右排序規則的原因是因為它允許更多優化空間(例如,操作可以重疊和交錯)並且具有更嚴格的排序規則將不利於程序的性能。 價值計算和副作用分別存在兩組獨立的規則。 (1)
因此,一個重要的區別是價值計算和副作用之間的區別。 值計算的順序始終由運算符優先級和關聯性決定。
任何運算符的操作數的值計算(但不是副作用)在運算符結果的值計算(但不是其副作用)之前排序。
使用這個例子,這意味着表達式(++a)
和b
的值必須在(++a)*b
之前計算,因為在不知道a
或b
的情況下,不可能計算它們的乘積,這意味着對於值計算,運算符優先級直接影響評估順序。
因此,在僅由值計算組成的 C++ 程序中,評估順序將完全由運算符優先級和關聯性決定。(2)
每次我以這種方式解釋時,我總是會遇到一個問題,如果未指定表達式c,d and e
in ((c/d)/e)
的計算順序,那么運算符優先級如何決定計算順序? 我總是回應說,只要在運算符結果的值計算之前對它們進行求值,操作數的求值順序就不會產生任何副作用,而不會產生副作用。 (3)
然而,這不適用於副作用。 a++
有副作用,即存儲在a
中的值遞增 1。因為副作用通常不按運算符優先級排序,這意味着++a
中的遞增可能發生在乘法之前、期間或之后(++a)*b
。 哎呀,它甚至可能發生在賦值運算符((++a)*b)+((c/d)/e)
的整個表達式的值計算之后。
因此,當排序不正確時,可能會導致未定義行為的副作用。 在沒有副作用的情況下,人們可以根據需要進行任意數量的相鄰無序的值計算。 (4)
在表達式((c/d)/e)
中,如果c,d or e
有副作用(例如,如果它們是修改全局值的函數),那么即使它們是在運算符的結果的值計算之前進行評估。
關鍵的要點是,每當有人談論評估順序和運算符優先級之間的區別時,他們的真正意思是“值計算排序與副作用排序”。
對我來說,值計算和副作用之間的區別對於理解評估順序和運算符優先級正確之間的區別至關重要。 我一直是這樣解釋的,但是在網上看很多解釋時,大多數人甚至都沒有提到這種差異,諸如“它們是相關的但不同的”之類的說法。
這是令人困惑的,因為值計算的評估順序與運算符優先級密切相關。 它是獨立於運算符優先級的副作用計算。
這讓我對自己的理解產生了一些疑問,所以我想問:我上面的解釋是否正確?
我想特別關注第 (1)、(2)、(3) 和 (4) 段。
不。
評估順序由運算符優先級決定。 也就是說,術語“評估順序”表示必須評估事物的順序,以便保持運算符優先級(和關聯性)不變量。
測序是另一回事,盡管相關。 排序只是意味着在評估表達式時,某些計算必須在其他計算之前、之后或不確定地完成。 排序規則的目的是在計算表達式的操作數時允許編譯器盡可能寬的范圍。
所有這些事情在編譯時都是已知的。
因此,在僅由值計算組成的 C++ 程序中,評估順序將完全由運算符優先級和關聯性決定。 (2)
不,值計算的評估順序並不完全由運算符優先級和關聯性決定。 它們僅對評估施加部分排序。
考慮a + b
。 在這種情況下,必須在a + b
之前評估a
和b
,但可以先評估a
或b
。
還要考慮(a + b) * (c + d)
。 在這里, a + b
和c + d
必須在(a + b) * (c + d)
之前計算,但是a
、 b
、 c
和d
可以按任何順序計算。 例如,允許的順序是b
, d
, c
, c + d
, a
, a + b
, (a + b) * (c + d)
。
通常,對於大多數運算符,運算符優先級和關聯性為表達式創建了一個樹結構,並且樹上的每個節點都必須在其父節點之前進行計算,但對其他分支上的節點沒有任何排序要求。 一些運算符,例如&&
和||
施加額外的約束,例如,如果計算右操作數,則必須在計算右操作數的任何部分之前完全計算左操作數。 並且某些運算符要求不計算一個操作數,例如sizeof
(除了,在 C [尚未在 C++ 中],當它的操作數是可變長度數組時)或條件運算符( a? b: c
中的b
或c
之一: a? b: c
未評估)。
關於您的其他編號段落,我看不出它們有任何錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.