38

関数呼び出しを検討してください(呼び出しint sum(int, int)

printf("%d", sum(a,b));

,コンパイラは、関数呼び出しで使用されているsum(int, int)がコンマ演算子ではない ことをどのように判断しますか?

: 関数呼び出しでコンマ演算子を実際に使用したくありませんでした。コンマ演算子ではないことをコンパイラがどのように認識しているかを知りたかっただけです。

4

6 に答える 6

49

C言語の文法を見てください。これは、標準の付録 A に完全に記載されています。これが機能する方法は、C プログラムの各トークンをステップスルーし、それらを文法の次の項目と照合できることです。各ステップで使用できるオプションの数は限られているため、特定の文字の解釈は、その文字が表示されるコンテキストによって異なります。文法の各ルール内で、各行はプログラムが一致する有効な代替手段を提供します。

具体的には、 を探すとparameter-list、明示的なコンマが含まれていることがわかります。したがって、コンパイラの C パーサーが「パラメーター リスト」モードの場合は常に、検出されたコンマは、コンマ演算子ではなく、パラメーター セパレーターとして理解されます。同じことが大括弧にも当てはまります (式でも発生する可能性があります)。

これが機能するのは、単純なルールではなく、ルールparameter-listを慎重に使用するためです。にはコンマを含めることができますが、 には含めることはできません。そうでない場合、文法があいまいになり、コンパイラはパラメーター リスト内でコンマを検出したときに何をすべきかわかりません。assignment-expressionexpressionexpressionassignment-expression

ただし、たとえば、関数定義/呼び出しの一部ではないif左角かっこ、または、while、またはforステートメントは、式の一部として解釈されます (他にオプションがないため、式の開始がはその時点で有効な選択です)、次に、括弧内でexpression構文規則が適用され、カンマ演算子が許可されます。

于 2013-06-29T19:06:25.270 に答える
26

C99 6.5.17 から:

構文で示されているように、コンマ演算子 (この節で説明されている) は、リスト内の項目を区切るためにコンマが使用されているコンテキスト (関数への引数や初期化子のリストなど) では使用できません。一方、括弧で囲まれた式内、またはそのようなコンテキストの条件演算子の 2 番目の式内で使用できます。関数呼び出しで

f(a, (t=3, t+2), c)

この関数には 3 つの引数があり、2 番目の引数の値は 5 です。

別の同様の例は、配列または構造体の初期化リストです。

int array[5] = {1, 2};
struct Foo bar = {1, 2};

コンマ演算子を関数パラメーターとして使用する場合は、次のように使用します。

sum((a,b))

もちろん、これはコンパイルされません。

于 2013-06-29T18:37:32.457 に答える
19

その理由は C 文法です。他の誰もが例を引用するのが好きなようですが、本当の取引は、標準 (C99) の関数呼び出しの句構造文法です。はい、関数呼び出しは()、後置式 (たとえば識別子など) に適用される演算子で構成されます。

 6.5.2 postfix-expression:
       ...
       postfix-expression ( argument-expression-list_opt )

一緒に

argument-expression-list:
       assignment-expression
       argument-expression-list , assignment-expression    <-- arglist comma

expression:
       assignment-expression
       expression , assignment-expression                  <-- comma operator

コンマ演算子は、の中でのみ使用できます。つまり、文法のさらに下にあります。そのため、コンパイラは、関数の引数リスト内のコンマを、 expressionを区切るものとしてではなく、assignment-expressions区切るものとして扱います。

于 2013-06-29T19:12:31.963 に答える
11

既存の回答は、「C言語の仕様では、演算子ではなくリストセパレーターであると述べているため」と述べています。

ただし、あなたの質問は「コンパイラーはどのように知っていますか...」と尋ねていますが、それはまったく異なります。コンパイラーがコンマインがprintf("Hello, world\n");コンマ演算子ではないことを知っている方法と実際には違いはありません。コンマが表示されるコンテキスト - 基本的に、以前に行われたもの。

C '言語' はBackus-Naur Form (BNF) で記述できます。基本的には、コンパイラのパーサーが入力ファイルをスキャンするために使用する一連の規則です。C の BNF は、言語内のコンマのこれらの異なる発生を区別します。

コンパイラがどのように機能するか、およびコンパイラの書き方に関する優れたリソースがたくさんあります。

于 2013-06-29T20:13:47.957 に答える
1

この質問には複数の側面があります。1つのパーは、定義がそう言っているということです。では、コンパイラはこのコンマがどのコンテキストにあるかをどのように知るのでしょうか? それがパーサーの仕事です。特に C の場合、言語は LR(1) パーサー ( http://en.wikipedia.org/wiki/Canonical_LR_parser ) で解析できます。

これが機能する方法は、パーサーが可能な状態を構成する一連のテーブルをパーサーが生成することです。特定の状態では特定の記号のセットのみが有効であり、記号は状態によって異なる意味を持つ場合があります。パーサーは、先行する記号により、関数を解析していることを認識しています。したがって、可能な状態にコンマ演算子が含まれていないことがわかります。

ここでは非常に一般的ですが、Wiki で詳細をすべて読むことができます。

于 2013-06-29T21:39:01.410 に答える