代码转换成可执行文件的全过程
看了一些网上的文章,觉的还是自己写写看看才能理解通透,也为找简历做准备。
代码转换成可执行文件分为4个步骤,预处理、编译、汇编、链接。
预处理
这个过程是执行代码中的一些预处理指令,多说无益,直接上代码
#include <iostream>
#define Best true;
#ifdef DEBUG
using namespace std;
#endif // DEBUG
int main()
{
Best;
printf("Hello World!\r\n");
return 0;
}
这是一个C++源码,等它预处理完成后会怎么样?
vs2019可以在项目属性-预处理器-预处理到文件夹-是,在项目的Debug文件夹中会有生成的.i文件。
#line 1 "D:\\CppRes\\Yidaoyun\\C++学习疑难\\VirtualFunction.cpp"
#pragma external_header(push)
#line 1 "D:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.29.30133\\include\\iostream"
#pragma once
#pragma external_header(push)
#line 1 "D:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.29.30133\\include\\yvals_core.h"
#pragma once
...
为什么用省略号,因为生成后的.i文件实在太长了,足足有64211行,拿出去也可以吹写了6w+行代码了hh(其实一半都是空行)。
可能有人会好奇,为什么预处理完成之后还有#pragma之类的预处理命令,我在该文件中find了一下,发现#include、#define、#ifdef之类的命令都不存在,所以可以得出,这三种命令应当是执行完了。
#include命令是将其他文件中的源码复制过来,这点应该很好理解;#define命令是将宏替换成定义,在我的代码中就体现为把所有Best替换为true;#ifdef则是判断条件,如果条件符合就将中间的代码加入到.i文件中,避免编译不需要的代码造成可执行文件冗余。
那么其他带#的命令是干嘛的呢?就不赘述了,唯一有一点比较好奇的是为什么预处理完成之后还有#pragma命令?
我有一种推测,.i文件里#line命令用于控制预定义宏,而#pragma跟代码一样作为指令控制系统和主机,两者都作为CPU的执行代码存在于.i文件中,不可被省略。
编译
这时需要对.i文件进行词法分析、语法分析、语义分析,我好像记得在搜索引擎里学过类似的概念这个讲起来比较复杂,回头留个专栏讲这个。
//TODO:编译原理
汇编
将源码转换为机器码,不过编译器会对机器码进行优化,生成.o文件即二进制可重定向文件。
链接
链接过程可分为静态链接和动态链接。静态链接即将不同.o文件的相似字段进行合并,生成可执行文件。动态链接即程序启动才将dll文件加入到exe文件中执行。
//TODO:研究静态链接和动态链接
参考文献
C/C++:编译全过程——预处理、编译、汇编、链接(包含预处理指令:宏定义,文件包括、条件编译)_怎么在devc++里面把c文件变成汇编语言-CSDN博客
C/C++ 预处理器参考 | Microsoft Learn
程序的静态链接,动态链接和装载 - Szz - 博客园 (cnblogs.com)
标签:文件,代码,C++,链接,编译,pragma,预处理 From: https://www.cnblogs.com/Isakura-red/p/18421461