1、编译与链接的区别是什么?
在多道程序环境中,想将用户源代码变成一个可在内存中执行的程序,通常可分为三步:编译、链接和载入。
编译
将预处理生成的文件,通过词法分析、语法分析、语义分析以及优化后编译成若干目标模块。可以理解为将高级语言翻译成二进制代码的机器语言。windows下编译成.obj文件,Linux下编译成.o文件。链接
由链接程序,将编译后形成的一组目标模块以及它们所需要的库函数链接在一起,形成一个完整的载入模型。链接主要解决相互引用的问题,分为地址和空间分配,符号解析和重定位几个步骤。在编译阶段生成目标文件时,会暂时搁置那些外部引用,而这些外部引用就是在链接时确定的。链接器在链接时,会根据符号名称去相应模块中寻找对应符号。带符号确定后,链接器会重写之前未确定的符号地址,这个过程称为重定位。链接一般分为:静态链接,载入时动态链接和运行时动态链接三种。载入
由载入程序将载入模块载入内存。
编译和链接是为将用户程序从硬盘上调入内存并将其转化为可执行程序服务的。编译时,编译器需要的是语法正确,函数与变量的声明正确。一般而言,每个源文件都应该对应于一个中间目标文件。链接时,主要是链接函数和全局变量,所以可以采用这些中间目标文件来链接应用程序。链接就是目标文件相互链接自己需要的函数和全局变量,而函数可能源于其他目标文件或库文件。
2、编译型语言与解释型语言的区别是什么?
编译型语言
编译型语言是指应用源程序执行之前,就将程序源代码“翻译”成目标代码(“机器语言”)保存在另一个文件中,因此目标程序可以脱离语言环境独立执行多次,使用比较方便,效率较高。但应用程序一旦需要修改,必须先修改源代码,只有目标文件没有源代码,则修改很困难。大多数软件产品都是应目标程序形式发布给用户,不仅可以直接运行,还可以使他人难以盗用其中的技术。C/C++/Fortran/Visual Foxpro/Psacal/Delphi等都是编译型语言。解释型语言
解释型语言相对于编译型语言存在的,源代码不是直接翻译成机器语言,而是先翻译成中间代码,再由解释器对中间代码进行解释运行。解释程序的任务是逐一将源程序的语句解释成可以执行的机器指令,不需要编译链接成目标代码后再执行,当语句出现语法错误,解释器可以立刻引起程序员的注意,程序员可以在开发阶段进行校正。每条语句只有在执行时,才被翻译,解释程序每执行一次,就翻译一次,因此效率低下且依赖解释器,但是其跨平台性好。Python/JavaScript / Perl /Shell等都是解释型语言。
Java是一类特殊的编程语言,其程序也需要编译,但是却没有直接编译称为机器语言,而编译为字节码,然后在Java虚拟机上一解释方式执行字节码。
3、如何判断一段程序是由C编译的还是由C++编译的?
如果编译器在编译cpp文件,那么自定义宏_cpluslus
就会被定义,如果是一个c文件被编译,那么_STDC_
就会被定义。_STDC_
是预定义宏,当它被定义后,编译器会按照ANSIC的标准来编译C语言程序。
C与C++编译方式不同。编写C/C++的兼容代码,需要如下格式:
#ifdef _cplusplus
extern "C"{
#endif
//code
#ifdef _cplusplus
};
#endif
4、extern “C”的作用是什么?
C++是一种面向对象语言,支持函数重载,而C语言是面向过程语言,不支持函数重载,所以函数在被C++编译后再库中的名字与C语言不同。如果声明一个float f(int a, char b)
,C语言一般使用类似_f
的内部名,而C++则将参数连在其中,内部名类似_f_int_char
。因此,链接器无法解释C++程序对C语言函数f的调用。
C++提供了C语言替代连接说明符号extern "C"
来解决名字匹配问题,该语句用在函数前:extern "C" float f(int a, char b)
,其目的是告诉编译器f()
是C连接的,不需要按照C++的方式转换函数名,这样就可以正确链接到f()
函数了。