簡體   English   中英

為什么“if(i ++ &&(i == 1))”false,其中i是一個保持值為1的int?

[英]Why is “if (i++ && (i == 1))” false where i is an int holding the value 1?

{
    int i = 1;
    if (i++ && (i == 1))
        printf("Yes\n");
    else
        printf("No\n");
}

根據我的理解,在if條件中,首先計算表達式( i==1 ),它應該返回1 ,然后它在邏輯上用1 ,這是i的值,所以表達式應該返回1 && 1 == 1 ,但執行了else部分。

有人可以解釋為什么else部分被執行?

在C中,在&&運算符的LHS評估與RHS評估之間存在一個序列點 ,必須在評估RHS之前完成增量並完成。 因此, i++ (相當於i++ != 0 )被執行並且增量完成(並且表達式的計算結果為true),所以在評估RHS時, i == 2因此整體表達式為false而你得到'不'打印。 如果&&運算符的LHS評估為false(0),則由於&&運算符的“短路”屬性,不會對RHS進行求值。

只有少數運算符具有在LHS和RHS的評估之間具有序列點的屬性: &&|| , (作為一個經營者,而不是作為一個參數列表分隔符) -這里面的? : ? :也是,這不是一個二元運算符,但是在評估條件之后和之后的表達式之前有一個序列點? 或者評估:之后的表達式(總是評估其中一個或另一個,但不是兩者)。

&&|| 運營商是唯一具有“短路”特性的運營商。 僅當LHS評估為真時才評估&&的RHS; ||的RHS 僅在LHS評估為false時進行評估。


關於序列點的澄清

Iwillnotexist Idonotexist正確斷言

C11標准沒有取消序列點,只有C ++ 11標准。

C ++ 11(ISO / IEC 14882:2011)說:

1.9程序執行

¶13 之前排序的是由單個線程(1.10)執行的評估之間的非對稱,傳遞,成對關系,這導致這些評估之間的部分順序。 給定任何兩個評估AB ,如果AB之前被排序,那么A的執行應該在B的執行之前。 如果AB之前測序,B不是A之前測序,則AB未測序 [ 注意:未經測試的評估的執行可能會重疊。 - 注完 ]評價AB當任一AB之前測序或A之前B被測序的測序不定 ,但它是未指定的哪個。 [ 注意:不確定順序的評估不能重疊,但可以先執行。 - 結束說明 ]

術語“序列點”根本不出現在C ++ 11中(唯一的近似匹配是'序列指針')。

C11(ISO / IEC 9899:2011)說:

5.1.2.3程序執行

¶3 之前排序的是由單個線程執行的評估之間的非對稱,傳遞,成對關系,這導致這些評估之間的部分順序。 給定任何兩個評估AB ,如果AB之前被排序,那么A的執行應該在B的執行之前。 如果A不是之前或B之后測序(相反地,如果AB之前測序,則BA 之后進行測序 。),則AB未測序 AB之前或之后進行測序時,評估AB不確定的 ,但是未指定哪一個。 13)表達式AB的評價之間的序列點的存在意味着,與A相關聯的每一個值的計算和副作用與B相關聯的每一個值的計算和副作用之前測序。 (序列點的摘要見附件C.)

13)未經測試的評估的執行可以交錯。 不確定順序的評估不能交錯,但可以按任何順序執行。

因此,C11確實保留了序列點,但使用與C ++ 11基本相同的術語添加了“之前排序”和相關術語。

在這里,一個簡單的解釋

在此輸入圖像描述

這就是為什么這種情況會變成'假'

當在表達式中使用&& ,保證從左到右計算其參數。 所以i將具有的值2(i==1)進行了評價。 因此,表達式為false, else部分將被執行。

但是,請注意完整性,如果左參數的計算結果為false或0,則根本不評估右參數。

我認為1 && 1 = 1和1 && 0 = 0對您來說很清楚。 Michael L的回答對我來說似乎很好。但我仍然會嘗試詳細說明一下。 這是提供運營商優先級列表的鏈接:

http://www.difranco.net/compsci/C_Operator_Precedence_Table.htm

如果您訪問此鏈接並參考該表,那么您將會知道&&已經從左到右關聯。所以首先我將在左邊部分變為2(Sruit嘗試使用圖表顯示這個);然后對於右邊部分我== 1檢查已完成。我們可以通過編寫如下所示的代碼來檢查:

該代碼解釋了當執行流程達到i == 1 part時i = 2。

#include <stdio.h>
int main() {

    int i = 1;
    if (i++ && (printf("%d\n",i)))
        printf("Yes\n");
    else
        printf("No\n");
    return 0;
}

所以輸出是:

2

所以2 == 1出來是假的,最終答案給人驚喜! 右側支架給出0和左側1,因此1 && 0 = 0。 我認為這很公平,可以理解。

你很困惑,因為在循環語句中, i ++用於后增量。 例如

for (i=0;i<1;i++)

在上面的循環程序中, i將首先獲得初始值並檢查條件。 if條件為真,因此它遞增i並將i計算為循環體的舊值,但在循環體外它具有新值1

在你的問題你正在使用if和老值范圍i在遇到邏輯運算符將結束它會自動獲得新的價值和增量2這樣的條件返回false。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM