27

序章

C/C++ のすべての教科書には、次のような演算子の優先順位と結合規則の表があります。

演算子の優先順位と結合規則の表

http://en.cppreference.com/w/cpp/language/operator_precedence

StackOverflow に関する質問の 1 つに、次のような質問がありました。

次の関数が実行される順序は次のとおりです。

f1() * f2() + f3();
f1() + f2() * f3();

前のチャートを参照すると、関数には左から右への結合性があると自信を持って答えたので、前のステートメントでは、両方の場合で次のように評価されます。

f1() -> f2() -> f3()

関数が評価されたら、次のように評価を終了します。

(a1 * a2) + a3
a1 + (a2 * a3)

驚いたことに、多くの人が私が完全に間違っていると言いました。それらが間違っていることを証明しようと決心した私は、ANSI C11 標準に目を向けることにしました。演算子の優先順位と結合性についてほとんど言及されていないことに、またしても驚かされました。

質問

  1. 関数は常に左から右に評価されるという私の信念が間違っているとすれば、関数の優先順位と結合性に関する表は、実際には何を意味するのでしょうか?
  2. ANSI でない場合、演算子の優先順位と結合性を定義するのは誰ですか? 定義を行うのが ANSI である場合、演算子の優先順位と結合規則についてほとんど言及されていないのはなぜですか? 演算子の優先順位と結合性は、ANSI C 標準から推測されますか、それとも数学で定義されていますか?
4

5 に答える 5

10

C 標準における演算子の優先順位は、構文によって示されます。

(C99, 6.5p3) 「演算子とオペランドのグループ化は、構文によって示されます。74)」

74) 「構文は、式の評価における演算子の優先順位を指定します」

C99の根拠も言う

「優先順位の規則は、各演算子の構文規則にエンコードされています。」

「結合規則は、同様に構文規則にエンコードされます。」

また、結合性は評価順序とは関係がないことに注意してください。の:

f1() * f2() + f3()

関数呼び出しは任意の順序で評価されます。C の構文規則では、そのf1() * f2() + f3()意味(f1() * f2()) + f3()は示されていますが、式のオペランドの評価順序は指定されていません。

于 2013-12-24T23:32:31.483 に答える
8

優先順位と結合性について考える 1 つの方法は、この言語では、複数の演算子ではなく、代入と 1 つの演算子を含むステートメントのみが許可されていると想像することです。したがって、次のようなステートメント:

a = f1() * f2() + f3();

5 つの演算子 (3 つの関数呼び出し、乗算、および加算) があるため、許可されません。この簡略化された言語では、すべてを一時変数に割り当ててから結合する必要があります。

temp1 = f1();
temp2 = f2();
temp3 = temp1 * temp2;
temp4 = f3();
a = temp3 + temp4;

結合性と優先順位は、最後の 2 つのステートメントをその順序で実行する必要があることを指定します。これは、乗算が加算よりも優先されるためです。ただし、最初の 3 つのステートメントの相対的な順序は指定されていません。次のようにすることも同様に有効です。

temp4 = f3();
temp2 = f2();
temp1 = f1();
temp3 = temp1 * temp2;
a = temp3 + temp4;

sftrabbit は、関数呼び出し演算子の結合性が関連する例を示しました。

a = f()();

上記のように単純化すると、次のようになります。

temp = f();
a = temp();
于 2013-12-24T23:41:54.690 に答える
4

優先順位と結合性は標準で定義されており、構文ツリーの構築方法を決定します。優先順位は演算子の種類 ( 1+2*3is1+(2*3)と not (1+2)*3) によって機能し、結合性は演算子の位置 ( 1+2+3is(1+2)+3と not 1+(2+3)) によって機能します。

評価の順序が異なります - 構文ツリーを構築する方法を定義するのではなく、構文ツリーevaluate内の演算子のノードを定義する方法を定義します。評価の順序は、定義されないように定義されています。コンパイラは、適切と思われる順序を自由に選択できるため、これに依存することはできません。これは、コンパイラがコードの最適化を試みることができるようにするためです。プログラマーは、評価の順序に影響されないコードを作成し、順序に関係なく同じ結果が得られるようにするという考え方です。

于 2013-12-24T23:40:36.303 に答える
3

左から右への結合性はf() - g() - h()(f() - g()) - h()それ以上のことはありません。を返すとしfます1。を返すとしgます2。を返すとしhます3。左から右への結合性とは、結果が(1 - 2) - 3、または であることを意味します。コンパイラは、結合性とは何の関係もないand-4を最初に呼び出すことは依然として許可されていますが、完全に異なるものになる の結果を与えることは許可されていません。gh1 - (2 - 3)

于 2013-12-24T23:33:37.223 に答える