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是指针,而不是数组,但这无关紧要,因为对数组的任何引用,除了 in sizeof,都有效地简化为指针。)

因此,当您说 时$$ = out,您指$$的是由 表示的存储out,而该存储即将消失。所以这行不通。你可以说$$ = $1,因为$1也是一个指向char的指针;这使得$$$1指向同一个字符。(这是合法的,但它使内存管理更加复杂。另外,你需要小心修改。)最后,你可以说strcpy($$, out),但这依赖于$$已经指向一个足够长out的字符串,这是极不可能的,因为它的意思是将 指向的存储复制到 指向out的位置$$

此外,正如我上面提到的,当您在 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 数据(包括strdupand的结果asprintf)存储在解析器堆栈(即 as $$)中也意味着free当您完成它时必须这样做;否则,您有内存泄漏。

于 2013-08-28T17:18:40.117 回答
0

我已经解决了它的问题$$ = out;strcpy($$,out);现在它可以正常工作了。

于 2013-08-29T13:37:02.830 回答