由于我选择的是C++,因此我选择的Linux的编辑器为gcc/g++。其中,gcc我们用来编译C语言,g++用来编译C++(由于C++兼容C,我们虽然可以用g++来编译c,但我们一般不会这么做)
在C语言中我们知道我们的文件要想被执行需要编译和链接,其中编译又分为预处理、编译和汇编。
预处理主要的工作是宏替换、去掉注释等,我们可以使用如下指令使编译器gcc将它的工作只做第一段预处理:
gcc -E test.c -o test.i(-E会让gcc预处理完后停止编译,-o指目标文件,预处理后的文件常用后缀.i)
编译将预处理后的文件翻译成汇编代码,在翻译之前还会检查语法等。
gcc -S test.i -o test.s(-E会让gcc编译完后停止)
汇编会将编译后的文件转成可执行文件
gcc -c test.s -o test.o(-c会让gcc汇编完后停止)
链接将可执行文件链接,链接后机器才可以执行(不然会不完整,编译器无法执行)
gcc test.o -o test
编译器自举
在此扩展两个问题:先有语言还是先有编译器?先有汇编语言还是先有汇编编译器?
想明白这两个问题,就明白什么是编译器自举了
指令集
指令集就是CPU 能看懂的全部命令清单,是 CPU 和软件之间的接口。我们所写的高级语言,计算机是看不懂的,都是先翻译成汇编语言,再翻译成二进制语言。翻译出来的二进制语言是有章法的(由编译器能读懂的指令集中的指令组成),如果不在指令集中的指令编译器就看不懂了(这一部分我们了解即可,这是编译器的任务)。
动静态库理解(入门)
我们所写的C语言代码编译工作完成了,但没有链接,它是无法执行的(比如printf函数我们没有实现,机器怎么执行此函数)。因此我们需要链接动静态库
在介绍动静态库之前我们先了解什么是动静态链接
静态链接是在编译时就将需要的文件就链接起来,从而形成可执行程序。它有两个致命的缺点:1、内存空间较大:因为每个可执行程序中对所有需要的目标文件都要有⼀份副本,所以如果多个程序对同⼀个目标文件都有依赖,如多个程序中都调用了printf()函数,则这多个程序中都含有 printf.o,所以同⼀个目标文件都在内存存在多个副本;2、更新较困难:每当库函数的代码修改了,这个时候就需要重新进行编译链接形成可执行程序(这是相对于动态链接而言)。但就是因为它的特性,它也有优点:在可执行程序中已经具备了所有执行程序所需要的任何东西,运行时间较快
动态链接是在运行时将需要的文件链接起来,形成可执行程序。它把程序按照模块拆分成各个相对 独立部分,在程序运行时才将它们链接在⼀起形成⼀个完整的程序。因此它的内存空间所需较小,更新也简单,但牺牲了一些运行时间。因此动态链接最常用
那什么是动静态库呢。库是我们所需要的函数的实现的地方,我们包含的头文件中只做了声明,真正的实现在库中。静态库是指编译链接(静态链接)时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名⼀般为“.a”。动态库是在程序执行时由运行时链接(动态链接)文件加载库,会节省系统的开销。动态库⼀般后缀名为“.so”,如libc.so.6 就是动态库。gcc在编译时默认使用动态库