目录
背景:
预处理:
编译:
汇编:
连接:
静态连接:
动态连接:
自动化编程make/makefile:
背景:
我们知道任何一个c语言或者c++文件想要生成一个可执行程序必须完成4个阶段,预处理、编译、汇编、连接。然而平时我们自己编写代码时,在vs环境或者其它编译环境当中并没有感受到这些变化,只感觉自己代码写好了,然后点击编译,程序即可运行,所以对于我们来说从编写文件到可执行文件只有一步的过程,事实上,这其中所有的操作都是我们的编辑器帮助我们完成了,我们也称这类编辑器为集成化编辑器。下面,我就给大家讲解编辑器在哪一步都做了些什么。
预处理:
预处理阶段为我们处理了宏定义、文件包含、条件编译、去注释操作,这样看有些抽象,请看下图。
首先看到我们的一个C语言文件,里面包含了头文件,宏定义,条件编译,还有注释。
在Linux中的生成预编译文件的指令为 gcc -E test.c -o test.i。文件名可以任意取值,保证后缀正确即可。
进入了我们的预编译完成文件之后,进入可以看到我们的#include<stdio.h>在文件中被展开成为了一大推的代码,这里我没有截取完全,里面的东西其实就是我们的库文件包含的内容在我们的机器中所存储了位置,也就是完成了我们的文件包含。
往下翻,找到最后,我们能看到宏定义不见了,全部在代码中被替换,原来主函数中的MAX和MIN都被替换为了100,0,但是在函数中定义的变量num还是保持原样。
里面的注释也全部被清除,其中test函数中的条件编译只保留了满足条件了那一部分,其余部分直接被清除。这些操作分别对应了宏定义、去注释、和条件编译。
编译:
编译过程就是将我们预编译文件转换为汇编语言文件。在这个过程当中就是我们的编辑器检查我们的代码是否规范、是否有语法错误。不过汇编语言我也没学过里面的内容看不懂,只是知道有这么一个过程。
其中部分内容我们还是能勉强阅读,比如有一个主函数main,还有文件名为test.c。
生成编译文件的指令为:gcc -S test.c -o test.s。
汇编:
汇编过程就是将汇编语言转换成为二进制代码,这一过程我们更加看不懂,当然也不需要我们看懂,毕竟这是给机器看的。
生成汇编文件的指令为:gcc -c test.c -o test.o。
连接:
通过使用ldd指令,可以得知我的文件使用了那些其它不是我们编写的文件。接下来我会为大家讲解两种不同的连接方式。
静态连接:
静态连接这一过程很简单,就像是我们与编译过程当中的头文件包含一样,它会将库文件当中的代码拷贝到我们的代码当中来,不过静态连接拷贝的函数是功能函数而不是头文件当中的代码。静态连接有一个很明显的优点就是它再完成连接之后,与库就不在相关联,就算此时删除库文件,我们的代码依旧能够跑过,但是它也有一个很致命的缺点就是,每调用一个函数,他就会拷贝一份,不管之前是否已经拷贝过。
生成一个静态连接代码操作为:gcc test.c -o myfile -static,就是正常的生成可执行文件操作,只不过它需要加上-static指令。
动态连接:
动态连接这一过程我们可以理解为,在我们的文件当中,调用的库文件函数都被转换成为了一个链接,当函数运行到这个位置时,函数会停下,进入链接,这个链接对应的就是库文件在我们电脑当中的位置,程序会运行到库文件当中,调用完成之后就会返回原位置,继续执行。这个操作的优点就是我们的文件数据不会特别的大,因为不用重复的调用同一个函数,或则不断地加入内容进入文件当中。它的缺点就是就算文件编译完成了,该可执行程序同样的依靠我们地库文件才能够实现功能。
编辑器默认生成动态链接文件,操作为:gcc test.c -o myfile。
通过比较上下两张图片,我们可以看到静态链接文件地大小时动态链接文件大小的100倍,差距十分的明显。
自动化编程make/makefile:
自动化编程的出现是因为,这里的每一条指令写起来都很麻烦,而且写错了之后有可能还会将我们的源代码给清除,这是我们很不想看到的,所以才出现了自动化编程make和makefile。
首先我们得通过touch创建一个makefile或者Makefile文件,然后通过vim进入该文件。
其中得myfile是自己命名的可执行文件名,后面的test.c代表需要编译的文件,下方则是需要执行的命令。
.PHONY:clean表示我们的清除操作可以反复执行。clean是自己命名的操作,与下方的clean:对应。
编辑完成之后退出,在命令框中写下make,即可默认执行第一个语句。如果想要执行第二条语句就需要写下make clean,也就是make加上功能。知道了这些,我们就可以写下多个不同的指令。其中的函数编译并不代表只能执行一次,而是可以同时编译多个源文件,只需要写好对应的关系即可。