Linux中,gcc/g++ 编译器。四个编译过程——预处理, 编译,汇编,链接。
文章目录
一、Linux编译器gcc和g++
(1)gcc/g++介绍
- gcc是编译c代码的编译器, g++是编译c++代码的编译器。
- c++代码的后缀有三种:①“.cpp”。②“.cc”。③“.cxx”。
(2)安装gcc-c++
sudo yum install -y gcc-c++
gcc --version // 查看gcc版本
g++ --version // 查看g++版本
(3)gcc使用
-
gcc最简单的使用。 gcc默认生成一个 **“a.out”**的可执行文件。
gcc test.c
-
使用**“-o”**选项可以指定生成的可执行文件名称。比如:“test.exe”。
gcc -o test.exe test.c gcc test.c -o test.exe
- 上述两种写法完全一样,没有区别。
-
使用指定的c标准进行编译。比如: **“-std=c99”**使用c99标准
gcc test.c -std=c99 // 使用c99标准 g++ test.cc -std=c++11 // 使用c++11标准
二、C/C++代码编译的过程
(1)预处理阶段(进行宏替换等)
-
在这个阶段,编译器gcc/g++主要对c源代码进行宏替换, 去注释, 头文件展开,和条件编译等,预处理后生成一个**“*.i”**后缀的c代码。
-
宏替换:例如:#define M 100,在预处理阶段,编译器将宏M 替换成100
-
去注释:在预处理阶段,编译器将所有的注释去除
-
头文件展开:将#include<stdio.h>包含的头文件从c标准库中拷贝到c源代码里。
-
条件编译:(可用于维护不同版本的软件,比如社区版,个人版,企业版)
#ifdef V1 // ... #elif V2 //... #else //... #endif
-
Linux中可以在命令行添加宏定义,“-D” 表示定义宏,紧接着的就是宏的名字和值。
gcc -D V1=1 test.c
-
-
-
实例:
gcc -E hello.c -o hello.i
- 其中 “-E”表示编译器从现在开始进行程序的翻译,预处理完成后,就停下来。
- “-o”表示指定生成的目标文件名称。
- ".i"文件是一个经过处理后的C代码初始文件。
(2)编译阶段(生成汇编代码)
-
编译器gcc/g++会检查代码的规范性,检查是否有语法错误,确定代码实际要做的工作,确定动态链接库的地址等,检查无误后,gcc将c代码翻译成汇编代码。
-
实例:
gcc -S hello.i -o hello.s
- “-S” 表示编译器从现在开始进行程序的编译,编译完成后,就停下来,并生成汇编代码。
- “.s" 文件里面是汇编代码。
(3)汇编阶段(生成机器可识别的二进制代码)
-
编译器gcc/g++将编译阶段生成的”.s“文件转成机器可识别的二进制目标代码(”.o“文件)。
-
实例:
gcc -c hello.s -o hello.o
- ”-c" , 编译器将.s文件转换成.o文件
- hello.o 是一个二进制文件,但是不能直接运行,因为还需要动态库里面的一些方法等。
(4)链接阶段(生成可执行文件或库文件)
-
在成功编译后就进入到链接阶段。gcc/g++让我们的程序和c标准库结合起来的过程。
-
gcc hello.o -o hello.exe
- 将hello.o 与动态库链接起来,生成可执行的二进制程序。
(5)总结
- 预处理: 进行宏替换,去注释,头文件展开,条件编译等,生成后缀为**“.i”**的c源代码。
- 编译: 将预处理阶段生成的“.i”c源代码,转换成“.s”的汇编代码。
- 汇编: 将编译阶段生成的“.s”文件,转换成".o"的二进制代码。
- 链接: 将汇编阶段生成的“.o”文件, 与库文件结合起来,生成可执行程序。
三、静/动态库
(1)静态库
-
静态库是指编译链接时,把库文件的代码全部加入到可执行程序中,因此生成的文件会比较大,但在运行时就不需要库文件了,有较好的可移植性和跨平台性。一般静态库后缀名为“.a”。
-
Linux中一般没有c/c++的静态库,需要我们自行下载:
// c静态库 sudo yum install -y glibc-static // c++静态库 sudo yum install -y libstdc++-static
-
静态库在Linux中的位置:
/usr/lib64/libc.a
(2)动态库
-
动态库与之相反,不需要将库文件拷贝到可执行程序中,而是在程序执行时由运行时的链接文件来加载库文件, 这样可以节省系统的开销,但是,一旦动态库丢失,所有的动态链接这个库的程序都无法执行。一般动态库后缀名为“.so”。
-
动态库在Linux中的位置:
/usr/lib64/libc.so.6 //==== libc.so.6 是 libc-2.17.so 的软链接,相当于快捷键 ==== // libc-2.17.so 与之在同一位置 /usr/lib64/libc-2.17.so
优缺点:
-
动态库和动态链接:不能丢失,但节省空间。
-
静态库和静态链接: 一旦形成和库无关,但拷贝会浪费空间。
注意:
-
在Linux 中,c/c++动态库是默认提供的, 而c/c++静态库是没有安装的。
-
gcc 默认生成的可执行程序, 默认采用动态链接。
(3)gcc默认生成的二进制程序,是动态链接的,使用file 指令可验证:
file my.exe
ldd my.exe
- file 指令:查看文件的具体类型。
- ldd指令:查看可执行程序所依赖的库。
(4)Windows 中的库
- 动态库后缀:“.dll”
- 静态库后缀:“.lib”