我试图生成与基本算术表达式相对应的3个地址代码。我之前没有使用lex和yacc工具(Newbie),我很难理解两者之间的控制/命令流程,即两个程序如何交互。
lex.l
%{
#include<stdio.h>
#include"y.tab.h"
int k=1;
%}
%%
[0-9]+ {
yylval.dval=yytext[0];
return NUM;
}
\n {return 0;}
. {return yytext[0];}
%%
void yyerror(char* str)
{
printf("\n%s",str);
}
char *gencode(char word[],char first,char op,char second)
{
char temp[10];
sprintf(temp,"%d",k);
strcat(word,temp);
k++;
printf("%s = %c %c %c\n",word,first,op,second);
return word; //Returns variable name like t1,t2,t3... properly
}
int yywrap()
{
return 1;
}
main()
{
yyparse();
return 0;
}
yacc.y
%{
#include<stdio.h>
int aaa;
%}
%union{
char dval;
}
%token <dval> NUM
%type <dval> E
%left '+' '-'
%left '*' '/' '%'
%%
statement : E {printf("\nt = %c \n",$1);}
;
E : E '+' E
{
char word[]="t";
char *test=gencode(word,$1,'+',$3);
$$=test;
}
| E '-' E
{
char word[]="t";
char *test=gencode(word,$1,'-',$3);
$$=test;
}
| E '%' E
{
char word[]="t";
char *test=gencode(word,$1,'%',$3);
$$=test;
}
| E '*' E
{
char word[]="t";
char *test=gencode(word,$1,'*',$3);
$$=test;
}
| E '/' E
{
char word[]="t";
char *test=gencode(word,$1,'/',$3);
$$=test;
}
| '(' E ')'
{
$$=$2;
}
| NUM
{
$$=$1;
}
;
%%
问题: getting garbage value in output
表达式(2 + 3)* 5 的预期输出应该如下:
t1= 2 + 3
t2= t1 * 5
获得输出:
t1= 2 + 3
t2= garbage value * 5
我无法弄清楚如何纠正这个问题。变量名称(例如t1,t2,t3)正在lex.l中的gencode()方法中正确返回
char *test=gencode(word,$1,'%',$3);
但是我完全不知道之后出了什么问题。我相信我没有正确处理$$,$1,$3
条款。
请帮助我了解出了什么问题,需要做什么以及如何做。 一点帮助和一些解释将非常有帮助。谢谢。
答案 0 :(得分:1)
这里的问题不在于使用弹性或野牛;相反,它是C代码中的未定义行为。
您的gencode
函数返回其第一个参数。然后你这样称呼它,粗略地说:
{
char word[] = ...
... = gencode(word, ...);
}
word
的生命周期在块完成时结束,这是在调用gencode之后。实际上,这与经典的悬空指针生成器没有区别:
char* dangle(void) {
char temporary[] = "some string";
return temporary;
}
这显然是不正确的,因为局部变量在返回其地址之前不再存在。
此外,您实际上创建了word
作为双字符数组:
char word[] = "t";
因为省略大小告诉C为初始字符串留下足够的空间(一个字符加上空终止符)。这没关系,但是你不能将更多的字符附加到字符串(strcat
),因为没有剩余的空间,你最终会覆盖其他一些变量(或更糟)。
答案 1 :(得分:-1)
mentall甚至不会在函数返回后结束。这就是为什么我在调用函数之前声明char word []的原因。 ideone.com/RBz0y2是我分别编写并在此处使用的代码。不对吗– Swagnik Dutta 16年3月9日在16:38 @novice:如果调用方在堆栈上分配并传递给被调用的函数,那很好。呼叫者仍然有记忆。但是,一旦呼叫者返回其呼叫者,内存就消失了。您不能将持久变量设置为该地址。所以,不,这是不对的。如果您需要保留将来的价值,则需要使用malloc进行分配;堆栈分配存储