[英]Confusion over operator precedence in C++
在以下測試表達式中說:
int ggg9 = fggg2() + (fggg3() && fggg4() < fggg5() * fggg6());
// 4 11 6 3
如果我們遵循運算符優先級 (顯示在表達式下方的注釋行中),則我假設將首先對parens中的表達式進行求值,然后將結果添加到fggg2()
。
因此,我假設它將按以下順序解決:
int r1 = fggg5() * fggg6(); //Precedence 3 (inside parens)
int r2 = fggg4() < r1; //Precedence 6 (inside parens)
int r3 = fggg3() && r2; //Precedence 11 (inside parens)
int ggg9 = fggg2() + r3; //Outside of parens, so it's last
(我將其轉換回C ++)
int i0;
int r2 = fggg2();
int r3 = fggg3();
if(!r3) goto L13;
int r4 = fggg4();
int r5 = fggg5();
int r6 = fggg6();
int i1 = r5 * r6;
if(r4 >= i1) goto L13
i0 = 1;
goto L14
L13:
i0 = 0;
L14:
int ggg9 = i0 + r2;
那么為什么當&&
運算符的優先級分別為&&
似乎先於*
,然后<
呢?
最后,為什么通過首先評估fggg2()
似乎並不關心parens? VS2017似乎最后評估了它。
從我看來, gcc
編譯器只是從左到右評估了所有這些功能,而沒有考慮優先級。
您正在將優先級與評估順序混淆。
這是一個非常常見的混亂。 可能是因為英語中的“ precede”一詞具有時間含義。 但這實際上是從等級層次的意義上講(例如here )。
在更簡單的表達式a() + b() * c()
, 優先級告訴我們*
運算符的操作數為b()
和c()
, +
的操作數為a()
且乘法。 一無所有,一無所有。
函數a,b,c
可能仍可以任何順序調用。
的確, *
的值計算必須在+
的值計算之前執行,因為我們需要知道前者的結果才能計算后者。
值計算是評估操作數的不同步驟。 必須先計算運算符的操作數,然后再計算其值,但沒有比這更嚴格的要求了。 沒有關於評估操作數的部分排序的規則。
的左操作數+
可能的右操作數之前評估+
,即使正確的操作是由許多子表達式。 編譯器可能會評估所有“葉”操作數,將結果存儲在堆棧中,然后執行值計算。
未必存在值計算的一個嚴格的順序任一,例如以w() * x() + y() * z()
這兩個值的計算*
可以按任一順序進行。
在您的代碼中, &&
運算符確實具有特殊的排序限制(有時稱為short )。 在開始評估右操作數之前,必須先評估左操作數。
優先級告訴我們&&
的左操作數是fgg3()
, &&
的右操作數是fggg4() < fggg5() * fggg6())
。 因此,要求在fgg4
, fgg5
和fgg6
任何一個之前調用fgg3()
。 在示例中,對操作數的求值順序沒有其他限制。 所述fgg2
可以發生在任何時間, 4
, 5
, 6
可以是任何順序,只要它們都是后3
。
您將運算符的優先級與求值順序混淆了,雖然可以保證保留優先級,但不求值順序,編譯器可以自由選擇該順序。
它可以首先在其他操作數的評估中間或之間評估fggg2()
。
您忘記了&&
運算符的短路評估因素。
&&
運算符的左側總是先於右側進行求值。
為了簡化操作,必須對r3
的前半部分求值,如果它的結果為false,則不會調用r1
和r2
任何一個。
C ++中需要進行短路評估。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.