为什么需要编译:编写好的代码最终翻译为机器可执行的二进制指令,编译的过程如下图所示:
编译预处理:在预编译过程中主要处理源代码中的预处理指令。
引入头文件 #include
条件编译指令:#ifdef, #ifndef, #else, #elif, #endif
条件编译指令 |
说 明 |
#if |
如果条件为真,则执行相应操作 |
#elif |
如果前面条件为假,而该条件为真,则执行相应操作 |
#else |
如果前面条件均为假,则执行相应操作 |
#endif |
结束相应的条件编译指令 |
#ifdef |
如果该宏已定义,则执行相应操作 |
#ifndef |
如果该宏没有定义,则执行相应操作 |
调用格式:
#if 条件表达式
程序段1
#else
程序段2
#endif
如果#if后的条件表达式为真,则程序段 1 被选中,否则程序段 2 被选中,必须使用 #endif 结束该条件编译指令。避免同一个头文件被多次包含、重复引用,最常用也是最简单的方法就是利用“#ifndef/#define/#endif”结构产生预处理块来防止头文件被重复引用。
如下面的示例代码所示:
#ifndef __HEADERNAME_H__
#define __HEADERNAME_H__
#include<string>
#endif
对于重复包含的头文件会忽略编译,这样提高运行的速度和效率,条件编译就用来控制预编译可以达成的条件。
编译:针对预处理后的文件进行词法分析、语法分析、语义分析、符号汇总、汇编代码生成,并针对程序的结构或者特定的CPU平台进行优化,简而言之就是: 将.cpp
源文件翻译成.s
的汇编代码。
汇编:将汇编代码.s
翻译成机器指令.o
文件,一个.cpp
文件只会生成一个.o
文件。
链接:汇编程序生成的目标文件即为.o文件,单独的.o文件可能无法执行。因为一个程序可能由多个源文件组成,此时就存在多个.o文件。文件A中的函数引用了另一个文件B中定义的符号或者调用了某个库文件中的函数,这就需要链接处理。那链接的目的就是将这些文件对应的目标文件连接成一个整体,从而生成一个可被操作系统加载执行的ELF程序文件。
静态链接:代码在生成可执行文件时,将该程序所需要的全部外部调用函数全部拷贝到最终的可执行程序文件中,在该程序被执行时,该程序运行时所需要的全部代码都会被装入到该进程的虚拟地址空间中。在Linux系统下,静态链接库一般以.a文件,我们可以将多个.o文件链接成一个静态链接库。
动态链接:代码在生成可执行文件时,该程序所调用的部分程序被放到动态链接库或共享对象的某个目标文件中,链接程序只是在最终的可执行程序中记录了共享对象的名字等一些信息,最终生成的ELF文件中并不包含这些调用程序二进制指令。在程序执行时,当需要调用这部分程序时,操作系统会从将这些动态链或者共享对象进行加载,并将全部内容会被映射到该进行运行的虚拟地址的空间。在Linux系统下,动态链接库一般以.so文件,我们可以将多个.o文件链接成一个动态链接库。
优缺点:静态链接浪费空间,每个可执行程序都会有目标文件的一个副本,这样如果目标文件进行了更新操作,就需要重新进行编译链接生成可执行程序(更新困难),优点就是执行的时候运行速度快,因为可执行程序具备了程序运行的所有内容;动态链接节省内存、更新方便,但是动态链接是在程序运行时,每次执行都需要链接,相比静态链接会有一定的性能损失。静态链接是由连接器完成的,动态链接最终是由操作系统来完成链接的功能,动态链接在不同的操作系统下可能由不同的实现原理,比如在Linux系统下,动态链接库通常以.so文件存在,在windows下同下,动态链接库一般以.dll文件存在。
标签:文件,程序,C++,链接,编译,endif,可执行程序 From: https://www.cnblogs.com/acec/p/16706842.html