1

私はバイソンでいくつかの問題を抱えています(再び)。$$ を使用して、文法ファイル内の「再帰規則」の間で文字列値を渡そうとしていますが、渡した値を出力すると、値ではなく間違った参照 ( AU�� ) のように出力されます。入力ファイルに書きました。

line: tok1 tok2
    | tok1 tok2 tok3
    {
        int len=0;
    len = strlen($1) + strlen($3) + 3;
    char out[len];
    strcpy(out,$1);
    strcat(out," = ");
        strcat(out,$3);
        printf("out -> %s;\n",out);
    $$ = out;
     }
     | line tok4
     {
        printf("line -> %s\n",$1);
     }

ここでは、コードの単純化された部分を報告しました。入力にトークン tok1 tok2 tok3 を与えると、$$ に out 変数を割り当てる必要があります (printf を使用すると、ルールの最初の部分で out 変数に正しい値があることがわかります)。tok4 を順番に照合する ルールの再帰部分にいます。しかし、$1 の値 ($$ を介して渡したので、out と等しいはずです) を出力すると、正しい出力が得られません。

4

2 に答える 2

4

以下は設定できません。

$$ = out;

参照する文字列outは、それが宣言されたブロックが終了するとすぐに、空中に消えようとしているからです。

これを回避するにmallocは、新しい文字列用のストレージが必要です。

また、ターミネーターの余地を残す必要があるため、必要です。strlen($1) + strlen($3) + 4;NUL

C には実際には文字列がないことを理解することが重要です。char( )へのポインターがありますchar*が、それらは実際にはポインターです。配列 ( char []) がありますが、配列を集約として使用することはできません。たとえばout = $1、配列に割り当てることができないため、コードでは違法になります。(また、は配列ではなくポインタですが、 を除く配列への参照は事実上ポインタに縮小される$1ため、それは問題ではありません。)sizeof

だからあなたが言うとき$$ = out、あなたは$$によって表されるストレージを指摘していてout、そのストレージはちょうど消えようとしています. だからうまくいかない。は char へのポインタでもある$$ = $1ため、と言えます。$1それは同じ文字を作り$$$1指します。(これは合法ですが、メモリ管理がより複雑になります。また、変更には注意が必要です。) 最後に、 と言うことができますが、それは を保持するのに十分な長さの文字列を既に指しているstrcpy($$, out)ことに依存しています。これは、 が指すストレージを が指す場所にコピーすることを意味するためです。$$outout$$

また、上で述べたように、C で「文字列」関数を使用している場合、それらはすべて、「文字列」引数 (つまり、文字へのポインタの引数) が指す文字のシーケンスを文字で終了する必要があると主張します0。 (つまり、文字 ではなく、コードが 0 の文字0)。

実際に文字列データ型を持つ言語でのプログラミングに慣れている場合、これはすべて少し奇妙に思えるかもしれません。練習は完璧を作る。

肝心なのは、次のように、文字列を格納するのに十分な大きさのストレージの新しい領域を作成する必要があるということです (不要なoutので削除しました)。

$$ = malloc(len + 1); // room for NUL
strcpy($$, $1);
strcat($$, " = ");
strcat($$, $3);
// You could replace the strcpy/strcat/strcat with:
// sprintf($$, "%s = %s", $1, $3)

mallocd データ ( and の結果を含むstrdup)asprintfをパーサー スタック (つまり、 as $$) に保存することは、使い終わったときにその必要性も意味することに注意してくださいfree。そうしないと、メモリ リークが発生します。

于 2013-08-28T17:18:40.117 に答える