编译和链接到底隐藏着什么?

Posted 燕麦冲冲冲

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了编译和链接到底隐藏着什么?相关的知识,希望对你有一定的参考价值。

写目录

一、预编译的花招

首先对在编译器下写好的文件hello.c进行如下指令

$gcc -E hello.c -o hello.i

-E 表示只进行预编译,这时候.c 文件全然已经变成.i 文件了。

我们需要了解的是,在这个过程中,预编译究竟耍了哪些花招。
若打开这个.i 文件,你将会发现:

1.1 所有的#define被删除,并且展开所有的宏定义

比如宏定义常量就会被换成切确的值,定义的字符也会被替换为原来的样子。

1.2 处理所有的预编译指令

比如:#if、#ifdef、#endif之类的。

1.3 #include包含的文件插入到.i 文件中

比如#include<stdio.h>中含有的文件内容会原封不动地放到.i 文件中。

1.4 删除所有注释或者批注

1.5 添加行号和文件名标识

这样做的目的是为了报错的时候信息能够准确指出相应的位置,是个相当人性化的设计,我愿称其为人类高质量程序员的发明。

二、编译才是大佬

对上述预编译完成的文件进行编译,即进行词法分析语法分析语义分析符号汇总后,可以得到汇编文件
但是上述四个步骤需要学习编译原理相关知识,对此我想对现在想用废话富有逻辑性的文字来凑字数的我(还没学过)说:“未来可期”。

相关指令:

$gcc -S hello.i -o hello.s

当然,如果你想直接一步就为,不去预编译:

$gcc -S hello.c -o hello.s

总的来说,编译做的事情最多而且最复杂,是个真正的大佬。

三、汇编是建设基层的好干部

汇编器是将汇编代码转化为机器能够读懂的机器指令和二进制代码。
没有复杂的语法,也没有语义,而且无需指令优化,做最底层的工作,但是尤为重要,是这一步才能让机器听懂人话。

指令:

$gcc -c hello.s -o hello.o

最终让.s 文件变成.o 文件。

四、看似多余的链接

可能你会有这样的疑惑:为什么编译器在编译的时候不直接输出一个可执行文件而是生成一个目标文件,这样啰嗦的操作究竟是为何?
其实,链接会把多个目标文件连接库进行链接,从而生成最终的可执行文件。

以上是关于编译和链接到底隐藏着什么?的主要内容,如果未能解决你的问题,请参考以下文章

NLP故事 | 讨好的冰山下,到底隐藏着什么

小花招解决Android 9 Pie 不能反射隐藏API限制

linux下的动态链接库和静态链接库到底是个什么鬼?动态链接库的编译与使用

到底牛在哪?深挖方舟编译器/EROFS超级文件系统

关于 DSO 引用隐藏符号的警告到底意味着啥?

C++程序编译之谜——简单还是复杂?编译到底有哪些步骤?