前言:
gcc/g++介绍:
gcc 和 g++ 是 GNU Compiler Collection 工具集中的两个主要工具,分别用于编译 C 和 C++ 程序。它们之间的主要区别在于语言的默认设置和链接的库。
我们知道在linux中,gcc指令编译.c后缀的文件,g++编译 .cpp后缀的文件。一个文件要想被编译成一个可执行文件要满足两个条件:一个是其文件类型可以被编译,另一个是文件内容可以被被编译。
假设我们在linux中用gcc/g++指令编译一个非以 .c/.cpp 后缀的文件,观察其结果
假设我们在linux中用gcc/g++指令编译一个以 .c/.cpp 后缀的文件,但是其内容无法正常编译,观察其结果
总结:一个文件要想被编译成一个可执行文件要满足两个条件:一个是其文件类型可以被编译(指gcc编译.c文件,g++编译.c++文件),另一个是文件内容可以被被编译。
1.必备知识
1. 预处理(进行宏替换)
2. 编译(生成汇编)
3. 汇编(生成机器可识别代码)
4. 连接(生成可执行文件或库文件)
2.gcc/g++基本编译指令(以gcc为例)
格式:
gcc [选项] 要编译的文件 [选项] [目标文件]
gcc选项
-E 只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面
-S 编译到汇编语言不进行汇编和链接
-c 编译到目标代码
-o 文件输出到 文件
-static 此选项对生成的文件采用静态链接
-g 生成调试信息。GNU 调试器可利用该信息。
-shared 此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库.
-O0 -O1 -O2 -O3 编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高 -w 不生成任何警告信息。
-Wall 生成所有警告信息。
2.1编译 c源文件生成可执行文件
gcc 文件名 -o 目标文件
2.2 查看 gcc
版本信息:
gcc --version
2.3预处理(生成预处理文件)
预处理功能主要包括宏定义,文件包含,条件编译,去注释等。-E选项让gcc在预处理结束后停止,生成一个仅预处理过的目标文件。
gcc -E filename.c -o output.i
这行指令的意思是,gcc从filename.c文件开始编译,到预处理阶段结束后马上停止,并生成目标文件。
2.4 编译(生成汇编)
在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查 无误后,gcc 把代码翻译成汇编语言。使用“-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码
gcc -S filename.c -o output.s
这行指令的意思是gcc编译器从文件filename.c开始编译,到编译阶段结束,生成汇编文件。 如果开始编译的文件是已经经过预处理的.i文件,那就不用再进行预处理。
2.5 汇编(生成机器可识别代码)
汇编阶段是把编译阶段生成的“.s”文件转成目标文件,在这个阶段会将汇编代码转换成机器可以识别的二进制代码。可使用选项“-c”就可看到汇编代码已转化为“.o”的二进制目标代码了。
gcc -c filename.c -o output.s
思路同上,编译器从filename.c开始,到汇编阶段结束后停止,生成机器可识别的二进制代码的 ".o"文件
2.6链接(生成可执行文件或库文件)
在成功编译之后,就进入了链接阶段。这个阶段会将 .o 目标文件连接成一个可执行文件,这也是编译器翻译的最后一个阶段。
gcc filename.c -o output
上述代码是将filename.c文件编译到可执行文件,中间经历了预编译、编译、汇编、链接四个阶段。也就是我们经常使用的一条指令。
3.函数库
函数库(Library,缩写为lib)分为 静态库和动态库。是一组已经编写好的代码,可供程序员在自己的程序中重复使用。这些代码可以包含函数、数据结构、对象等,用于完成特定的任务。函数库的使用有助于提高代码的可维护性、重用性和可扩展性。
比如, 我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有printf函数的实现,那么,是在哪里实现了“printf”函数的呢?
系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到 系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函数“printf”了,而这也就是链接的作用。
3.1静态库与动态库的区别:
静态库(Static Library):
- 编译链接时,把库文件的代码全部加入到可执行文件中,生成的文件比较大,形成一个独立的可执行文件。
- 静态库的文件扩展名通常为
.a
(在Unix/Linux系统)或.lib
(在Windows系统)。 - 静态库的优点是它可以在编译时将库的代码嵌入到程序中,使得程序在运行时不再依赖于外部的库文件。
动态库(Dynamic Library):
- 动态库在编译链接时并没有把库文件的代码加入到可执行文件中,在运行时被加载到内存中,这样能节省系统的开销,程序在需要时调用动态库中的函数。
- 动态库的文件扩展名通常为
.so
(在Unix/Linux系统)或.dll
(在Windows系统)。如前面所述的 libc.so.6 就是动态 库。gcc 在编译时默认使用动态库。完成了链接后,gcc 就可以生成可执行文件。 - 动态库的优点是它可以被多个程序共享,减小了程序文件的大小,同时允许在不修改程序代码的情况下更新库文件。
3.2修改链接方式
gcc -static your_program.c -o your_program_static
使用 -static
选项告诉编译器进行静态链接
4. file指令
file
命令用于确定文件的类型,也可以使用file命令来查看生成的二进制程序是动态链接的还是静态链接的。
格式是:file+二进制程序