判断编译器
① 在C/C++程序中,怎样可以知道编译器是GCC或G++
如果是gcc在预编译的时候会有一个名叫__GLIBC__的宏,如果是g++会有一个叫做__GLIBCXX__的宏,如果想知道版本可以用宏
#ifdef __GLIBC__
int main () //gcc
#elif __GLIBCXX__
int main() //g++
另外,gcc和g++都不完全算是纯编译器,两个只有连接器的区别,编译的方式是基本一样的
② 如何判断编译器所编译的文件是C方式还是C++的方式编译的
没有办法区分。C++是兼容C的,所以在C++代码中出现一两句C的语句也很正常,比如printf之类。(有时候printf确实比cout好用,但是scanf不如cin是一定的)所以只能根据后缀区分吧。
③ 如何在c语言中用宏来判断当前编译器
热心网友
一.
#define是C语言中提供的宏定义命令,其主要目的是为程序员在编程时提供一定的方便,并能在一定程度上提高程序的运行效率,但学生在学习时往往不能理解该命令的本质,总是在此处产生一些困惑,在编程时误用该命令,使得程序的运行与预期的目的不一致,或者在读别人写的程序时,把运行结果理解错误,这对 C语言的学习很不利。
1#define命令剖析
1.1 #define的概念
#define命令是C语言中的一个宏定义命令,它用来将一个标识符定义为一个字符串,该标识符被称为宏名,被定义的字符串称为替换文本。
该命令有两种格式:一种是简单的宏定义,另一种是带参数的宏定义。
(1) 简单的宏定义:
#define <宏名><字符串>
例: #define PI 3.1415926
(2) 带参数的宏定义
#define <宏名> (<参数表>) <宏体>
例: #define A(x) x
一个标识符被宏定义后,该标识符便是一个宏名。这时,在程序中出现的是宏名,在该程序被编译前,先将宏名用被定义的字符串替换,这称为宏替换,替换后才进行编译,宏替换是简单的替换。
1.2 宏替换发生的时机
为了能够真正理解#define的作用,让我们来了解一下对C语言源程序的处理过程。当我们在一个集成的开发环境如Turbo C中将编写好的源程序进行编译时,实际经过了预处理、编译、汇编和连接几个过程,见图1。
④ 程序如何自主区分不同编译器
一般选取编译器默认的宏
也可以在makefile里面指定可读性更好的宏
比如,区分mingw和gcc,就可以用mingw自带的WIN32来区分
⑤ 怎样判断c语言编译器好坏
for语句的判断句是在前的,也就是先进行判断,结果是真才执行循环体,这是for语句的模式。如果你希望判断在后的话可以用do-while语句.
⑥ 编译器如何实现if then else 判断(yacc之类自动构造,非手工)
上括号或者定义块
⑦ 如何在C语言中用宏来判断当前编译器
1、_MSC_VER 是微软C/C++编译器——cl.exe 编译代码时预定义的一个宏。需
要针对cl 编写代码时, 可以使用该宏进行条件编译。
2、_MSC_VER 的值表示cl 的版本。需要针对cl 特定版本编写代码时, 也可以使用
该宏进行条件编译。
3、_MSC_VER 的类型是"int",具体版本号定义如下:
MS VC++ 9.0 _MSC_VER = 1500
MS VC++ 8.0 _MSC_VER = 1400
MS VC++ 7.1 _MSC_VER = 1310
MS VC++ 7.0 _MSC_VER = 1300
MS VC++ 6.0 _MSC_VER = 1200
MS VC++ 5.0 _MSC_VER = 1100
其中MS VC++ 9.0 就是Visual C++ 2008,MS VC++ 8.0 就是Visual C++2005。
二、介绍预定义宏“__GNUC__”
1、__GNUC__ 是gcc 编译器编译代码时预定义的一个宏。需要针对gcc 编写代码时,
可以使用该宏进行条件编译。
2、__GNUC__ 的值表示gcc 的版本。需要针对gcc 特定版本编写代码时,也可以使
用该宏进行条件编译。
3、__GNUC__ 的类型是“int”
三、预定义宏"__MINGW32__"
1、MinGW编译器
四、symbian sdk 预定义宏:
symbian 平台,定义"__SYMBIAN32_"
3rd MR 版及之前的那个3rd 版本,定义"__SERIES60_30__"
3rd FP1 版,定义"__SERIES60_31__"
3rd FP2 版,定义"__SERIES60_32__"
另外,还有一个"__SERIES60_3x__"。若不需区分具体是哪一个3rd 版,则用之。
⑧ 如何知道电脑里有哪些编译器
可以看下环境变量PATH的值,一般安装的编译器会在这里设置路径。
⑨ 关于如何判断gcc之类的编译器的编译结果
我们再使用gcc编译的时候可以让他的输出信息保存到文件当中
gccmain.c-omain&>status.txt
上面的命令就是将gcc编译的信息保存到status.txt文件中,然后我们再程序中读取文件,看文件是否有内容,没有内容就说明没有报错和警告,编译成功。有内容就对每一行内容进行判断,看是warring还是error,只有warring也代表编译成功,有error代表编译失败,然后把这些报错信息都打印出来就好了。
下面看一下例子:
⑩ 编译器本身是如何进行测试的
编译器最重要的性质就是保证语义的正确。比如,从高级语言翻译到机器指令之后,指令必须正确的表达原来程序的意思。所以一般编译器测试都包含一些源程序,用来覆盖可能出现的各种情况。基本的原则是:原来程序的结果 = 编译后机器指令运行的结果。机器指令运行的结果很容易知道,运行一下就知道了。可是原来程序的结果你怎么知道呢?
为了解决这个“原来程序语义”的问题,最好是写一个解释器,准确无误的表达原来的代码的语义。所以我们的要求就是:
高级语言解释器(源程序) = 机器执行(机器代码)
由于处理器其实就是一个用来执行机器代码的解释器,这里有一个很美好的对称关系:
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 的正确性了。
这些是基本的语义测试原理。另外除了语义,可能还有一些“表面”一些的测试,它们看代码本身,而不只看它的语义。比如尾递归优化的测试应该确保输出程序的尾递归得到正确的处理,等等。这些是语义测试检查不到的,因为尾递归没有正确处理的程序大部分也能输出正确的结果。
普通的单元测试方法也可以用来测试一些编译器里的辅助函数,但那些不是编译器特有的,所以就不讲了。
另外,就像所有测试的局限性一样,你没法枚举所有可能出现的输入,所以以上的测试方法其实也不能保证编译器的完全正确。