12

私が知っているように、論理演算子&&はよりも優先され||ます。コードの実行時:

#include <stdio.h>

int main()
{
    int i = 1, j =1, k = 1;

    printf("%d\n",++i || ++j && ++k);
    printf("%d %d %d",i,j,k);

    return 0;
}

出力を与えています:

1
2 1 1

++i || ++j && ++kが次のように評価され た場合にのみ可能です。

(++i) || (++j && ++k)

ただし、演​​算子の優先順位規則に従って、次のように評価する必要があります。

(++i || ++j) && (++k)

したがって、出力は次のようになります。

1
2 1 2

これで何がうまくいかないのですか?

注:私の理解では、優先順位の高い演算子は次のように評価されると思います(連想が残っている場合):
1.左の式を評価します
2.次に、右の式を評価します(必要な場合)

間違っていますか?

4

4 に答える 4

13

||演算子は短絡します。最初のオペランドが true (ゼロ以外) と評価される場合、2 番目のオペランドは評価されません。

これは にも当てはまり&&ます。最初のオペランドが false の場合、2 番目のオペランドは使用されません。これは可能な最適化です。ブール値 OR true は true であり、同様にブール値 AND false は常に false であるためです。


OK、優先順位と評価順序を混同しています。ここで矛盾することはまったくありません。

++i || ++j && ++k

としてグループ化されます

(++i) || (++j && ++k)

&&のほうが優先度が高いからです。ただし、OR 演算の LHS は true であるため、AND 演算を含む RHS 全体が破棄され、評価されません。


編集中のメモ: はい、あなたは間違っています: 演算子の優先順位は、評価の順序と同じではありませんあくまでもグルーピングです。

于 2013-07-02T18:08:14.470 に答える
10

まず、あなたが自分で言ったように、&&優先順位が高くなります。つまり、オペランドのグループ化は

 (++i) || (++j && ++k)

「演算子の優先順位に従って」と言っている理由は(++i || ++j) && (++k)、私には明らかではありません。それはあなたが自分で言ったことと矛盾しています。

次に、演算子の優先順位は評価の順序とはまったく関係ありません。演算子の優先順位は、演算子とそのオペランド間のグループ化を決定します (つまり、演算子の優先順位は、どのオペランドがどの演算子に属するかを示します)。

一方、評価の順序はまったく別の話です。未定義のままであるか、まったく異なる一連のルールによって定義されています。||and演算子の場合、&&評価の順序は実際には左から右に定義されます (可能な限り早期に完了することが必須です)。

したがって、演算子の優先順位規則により、グループ化は次のようにする必要があることがわかります。

 (++i) || ((++j) && (++k))

ここで、評価順序規則は、最初に を評価し++i、次に (必要に応じて) を評価し++j、次に (必要に応じて) を評価し++k、次に を評価&&し、最後に を評価することを示して||います。

于 2013-07-02T18:12:24.533 に答える
9

あなたは言う:

++i || ++j && ++kが次のように評価された場合にのみ可能です。

(++i) || (++j && ++k)

ただし、演​​算子の優先順位規則に従って、次のように評価する必要があります。

(++i || ++j) && (++k)

&&の優先順位が の優先順位よりも高いため、最初のグループ化は正しいです||。次に、式は全体として の LHS を評価し、||をインクリメントするという副作用がありi、これは true と評価されます。つまり、式全体の真偽を判断する必要がないため、||(&&式) の RHS はまったく評価されません。

したがって、コンパイラは正しいです。何らかの方法で優先順位を誤解しています。


最初のグループ化が正しいのはなぜですか? 最初のグループ化によると、||よりも優先順位が高くなり&&ます。何がうまくいかないのですか?

優先順位を理解していないか、優先順位と評価の順序の相互作用を理解していないようです。最初のグループ化は、より高い優先順位を与えます&&

があればa + b * c*よりも優先順位が高く+、 と評価されa + (b * c)ますね。+to||*toを変更する&&と、式は同形であり、解釈は似ています。

算術式と論理式の大きな違いは、論理式のオペランドは左から右に評価する必要がありますが、算術式のオペランドは評価しないことです。コンパイラは評価b * cする前に評価できますa(ただしb * c、加算を行う前に評価する必要があります)。対照的に、論理式 ( a || b && c) では、コンパイラは を評価aする前に評価する必要があり、 が真であることが判明した場合、b && corはおろか、どちらも評価してはなりませabcb && c

于 2013-07-02T18:14:17.153 に答える