㈠ C加加用哪个编译器测试
vc6.0, vs2013,2015, dev cpp, codeblocks等。
㈡ C#编写的编译器,实现词法分析和语法分析功能!!求运行文件和代码示例!!
算你强。C#的编译器roslyn开源了,有空你自己去研究下吧。
dotnet/roslyn
https://github.com/dotnet/roslyn
㈢ 编写程序,程序是人写,编译器却测试,它怎么知道在哪里写错了,
因为它有自己的规则,你不按规则写程序就要报错呗
㈣ c语言编程怎么测试程序的对错
编译器会根据C语言的规则来判断你是否有语法错误,但是不能判断语意错误,即设计错误。
㈤ 求一个尽量完整的编译器:词法分析器+语法分析器
在一个模式被匹配之前,词法分析器往往需要超前扫描该词素后面的若干个字符,使用将字符退回输入流的方法,需要移动大量字符的时间,由于 词法分析器是编译期间唯一需要逐一扫描源程序字符的过程,因此它的效率将极大的影响编译器的性能,因此人们发明了双缓冲区的技术。
双缓冲区技术原理如下:
把一个缓冲区分成前后两个部分,每部分能够容纳N(1024/4096)个字符,每次系统读命令读入N个字符到前半部分或者后半部分,如果剩余的不足N个字符,则在最后增加一个不同于其他任何字符的字符,如eof/#,用于标识源文件的结束。缓冲区包括两个指针beginning和forward,在两个指针之间的字符串就是当前的词素。一开始两个指针都指向第一个字符,然后forward向后扫描,直至发现一个匹配的词素为止。如果forward跨过中间标记,则往后半部分读入N个字符。如果forward指针移过最后位置,则向前半部分读入N个字符,且forward指针重新指向开始继续处理过程。为了处理方便在两个部分的最后都增加一个文件结束标识eof。示意图如下:
______________________________________________________________________
|............for......while.... ........................................ |....int i .................................................. ...................| |_______________________________eof|_______________eof________________eof|
| |
beginning forward
下面是双缓冲区的一个c实现:
#include <stdio.h>
#include <string.h>
#define MAXWORD 1000
struct bibuffer
{
char* buffer[2048]; //缓冲区空间
char* beginning,forward; //前向和后向指针
int count; //前向指针记数
} bbuf;
void parse(char c)
{
if(c=' ')
{
memcpy(word[i],beginning,(size_t)(forward-beginning));
i++;
}
else forward++;
}
int main(int argc,char* argv)
{
File* fp;
char* word[MAXWORD];
int i=0;
buffer=new char[2048];
fp=open("test.c","r");
read(fp,buffer,1023);
buffer[1023]='#';
read(fp,buffer+1024,1023);
buffer[2047]='#';
bbuf->buffer=buffer;
bbuf->beginning=bbuf->forward=bbuf->buffer;
bbuf->count=0;
while(1)
{
forward=forward+1;
if(count==1023)
{
read(fp,buffer+1024,1023);
forward++;
//这个函数的具体代码就要和具体的词法分析规则而定,这里假设只识别空格分割的单词
parse(*forward);
}
else if(count>=2048)
{
read(fp,buffer,1023);
forward=bbuf->buffer;
//这个函数的具体代码就要和具体的词法分析规则而定,这里假设只识别空格分割的单词
parse(*forward);
}
else if(count!=1023&&count<2048&&(*forward)='#')
{
break; //词法分析结束
}
}
}
㈥ 为什么编译器需要复杂的语法
新的版本都是基于旧的版本升级过来的,以此来改善编译器的性能、增加对新平台的支持以及提高竞争能力。不同的编译器支持的标准语法是一致的(不然没资格称C编译器),但是每个编译器自身可以添加额外的语法、库来扩展语言的表达能力,这就是所谓的xx编译器扩展。使用语言扩展通常能获得较高的性能和灵活性,但是损失了跨平台性。不仅仅是编译器有很多版本,语言本身都有很多版本,目前C语言的版本是C11,下一个版本为C1y。
㈦ 编译器本身是如何进行测试的
编译器最重要的性质就是保证语义的正确。比如,从高级语言翻译到机器指令之后,指令必须正确的表达原来程序的意思。所以一般编译器测试都包含一些源程序,用来覆盖可能出现的各种情况。基本的原则是:原来程序的结果 = 编译后机器指令运行的结果。机器指令运行的结果很容易知道,运行一下就知道了。可是原来程序的结果你怎么知道呢?
为了解决这个“原来程序语义”的问题,最好是写一个解释器,准确无误的表达原来的代码的语义。所以我们的要求就是:
高级语言解释器(源程序) = 机器执行(机器代码)
由于处理器其实就是一个用来执行机器代码的解释器,这里有一个很美好的对称关系:
interp1(L1) = interp2(L2)
另外还有一个问题,就是编译器一般需要经过多个转化步骤(叫做 pass)才能最后编译为机器指令。比如,
L2 = pass1(source)
L3 = pass2(L2)
L4 = pass3(L3)
Ln = passN(Ln-1)
machine_code = codegen(Ln)
由于源程序经过了很多步骤猜得到最后的机器指令,如果你使用上面的公式,就会出现以下一些情况:
1. 知道结果错了,但是却不知道到底是哪一个 pass 错了。
2. 结果没有错,但是中间却有 pass 实际上是错的。但是由于之前的 pass 把输入程序的一些结构给“优化”掉了,所以错的那个 pass 其实没能得到触发错误的那个数据结构。所以测试没能发现错误。如果以后前面的那个 pass 被修改,错误就会暴露出来。这是非常难以发现的潜伏的危险。
为了防止这些情况出现,一些编译器(比如 Chez Scheme 和 Kent Dybvig 的课程编译器)使用了对每一个 pass 进行测试的做法。具体的方法就是为每一个中间语言都写一个解释器,把这语言的语义完全的表示出来。这样我们就需要检查一组等式:
L2 = pass1(source)
高级语言编译器(源程序) = interp2(L2) // 测试 pass1 的正确性
L3 = pass2(L2)
interp2(L2) = interp3(L3) // 测试 pass2 的正确性
这样一来我们就能独立的判断每一个 pass 的正确性了。
这些是基本的语义测试原理。另外除了语义,可能还有一些“表面”一些的测试,它们看代码本身,而不只看它的语义。比如尾递归优化的测试应该确保输出程序的尾递归得到正确的处理,等等。这些是语义测试检查不到的,因为尾递归没有正确处理的程序大部分也能输出正确的结果。
普通的单元测试方法也可以用来测试一些编译器里的辅助函数,但那些不是编译器特有的,所以就不讲了。
另外,就像所有测试的局限性一样,你没法枚举所有可能出现的输入,所以以上的测试方法其实也不能保证编译器的完全正确。
㈧ C编译器问题。不同编译器中编写C/C++程序语法是否有不同
for(int i=0;i<10;++i) cout<<i;
cout<<i;
Dev-c++里,是错的。i的作用域只是for
vc6.0里是对的。
这只是c++的写法。c里变量声明必须放在前面,不会有这种情况。
其他的没用过。
㈨ c语言改错 怎么通过编译程序检查出语法错误
编译器编译时对你的代码错误自动显示出来,告诉你错在何处,为什么错,你可以根据显示的错误改正代码