gcc的使用
目录:
1.什么是gcc
GCC(GNU Compiler Collection)是一个开源的编程语言编译器集合,最初由 GNU 项目开发。它支持多种编程语言,包括 C、C++、Objective-C、Fortran、Ada 等。GCC 是许多操作系统(如 Linux 和 Unix)的默认编译器。
概念:
- gcc 是 GCC 中专门用于编译 C 语言的命令。使用
gcc
命令可以编译 C 语言的源代码文件(后缀通常是.c
),将其转换为可执行文件。虽然它主要用于编译 C 程序,但gcc
也可以用于其他语言的编译,如果通过正确的选项配置。 - g++ 是 GCC 中专门用于编译 C++ 语言的命令。使用
g++
命令可以编译 C++ 源代码文件(后缀通常是.cpp
或.cc
)。虽然gcc
也可以编译 C++ 代码,但g++
针对 C++ 做了额外的处理,例如自动链接 C++ 标准库。因此,编译 C++ 程序时,通常使用g++
而不是gcc
。
关系总结:
- GCC 是整个编译器套件的名称,支持多种编程语言。
- gcc 是 GCC 中的一个工具,专门用于编译 C 语言代码。
- g++ 是 GCC 中的另一个工具,专门用于编译 C++ 语言代码。
2.gcc编译过程
- 预处理
- 功能:预处理器处理以
#
开头的指令,进行代码的预处理。 - 主要任务:
- 宏替换:处理
#define
指令,将宏替换为其对应的值。 - 文件包含:处理
#include
指令,替换为所包含文件的内容。 - 条件编译:处理条件编译指令,如
#ifdef
、#ifndef
和#endif
,决定哪些代码片段应该被包含或排除。
- 宏替换:处理
- 输出:生成一个扩展后的 C 源文件(通常以
.i
后缀),所有的宏和包含文件已被处理,结果是一个“干净”的源代码文件。
- 功能:预处理器处理以
- 编译
- 功能:将预处理后的源代码转换为汇编语言。
- 主要任务:
- 语法分析:分析代码的语法结构,构建语法树,检查语法错误。
- 语义分析:检查代码的语义正确性,如变量类型和作用域,确保变量在使用前已定义。
- 优化:根据编译器的设置进行一些基本优化,以提高生成代码的效率。
- 输出:生成一个汇编语言文件(通常以
.s
后缀),包含对应于源代码的汇编指令。
- 汇编
- 功能:将汇编语言代码转换为机器语言,生成目标文件。
- 主要任务:
- 翻译指令:将汇编语言的指令翻译为对应的机器语言指令。
- 生成符号表:记录代码中使用的变量和函数名及其地址,供链接器使用。
- 处理数据段:分配内存空间以存储变量和常量,生成数据段和代码段。
- 输出:生成一个目标文件(通常以
.o
后缀),其中包含机器代码和符号信息,但还不是可执行文件。
- 链接
- 功能:将一个或多个目标文件和库文件合并,生成最终的可执行文件。
- 主要任务:
- 符号解析:解析各个目标文件中的符号,将其地址绑定到具体的内存地址。
- 地址重定位:调整代码和数据段中的地址引用,以确保它们在最终可执行文件中是正确的。
- 合并段:将不同目标文件的代码和数据段合并为一个整体,生成可执行文件。
- 库链接:将所需的库(如标准库)链接到可执行文件中,确保程序能够调用库中的函数。
- 输出:生成一个可执行文件,用户可以直接运行。
3.函数库
- 在链接时,库链接链接的库就是函数库。
- 我们在C语言中调用的
printf
函数,在头文件stdio.h
中只有声明,没有实现。- 类似
printf
的实现,都被放在了函数库里
概念:函数库是指一些预定义的、可重用的函数集合,开发人员可以直接调用这些函数,而不必重新编写代码。函数库是程序开发的重要组成部分,帮助提高代码的效率和可维护性。根据库的链接方式,将函数库分为静态库和动态库。
3.1静态库
- 静态库在编译时被链接到可执行文件中。
- 编译后的可执行文件包含所有使用到的库代码,因此可执行文件相对较大。
- 一旦编译完成,静态库就不需要在运行时存在。
- 静态库的文件扩展名通常是:
- 在 Linux 系统中为
.a
- 在 Windows 系统中为
.lib
- 在 Linux 系统中为
优点:无需依赖外部库文件,适合独立运行的程序。
缺点:可执行文件体积较大,库的更新需要重新编译。
Linux下常见存放位置:
- 系统级库路径:
/usr/lib/
:大多数系统库的存放位置,适用于 32 位和 64 位库。/usr/local/lib/
:手动安装或本地编译的软件库的默认路径。/lib/
:一些系统关键的静态库也可能存放在这里。
- 自定义路径:如果你编译或安装了自定义库,静态库可能存放在自定义路径,比如
/opt/lib/
或用户自定义的目录下。
3.2动态库
- 动态库在运行时动态加载,并不会在编译时直接链接到可执行文件中。
- 动态库可以被多个程序共享,因此可执行文件体积较小。
- 运行时,操作系统会寻找并加载动态库
- 动态库的文件扩展名通常是:
- 在 Linux 系统中为
.so
(共享对象) - 在 Windows 系统中为
.dll
(动态链接库)
- 在 Linux 系统中为
优点:
- 可执行文件体积小,库更新方便(无需重新编译可执行文件)。
- 允许多个程序共享相同的库资源。
缺点:程序运行时依赖于外部库文件,若找不到对应的库,程序将无法运行。
Linux下常见存放位置:
- 系统级库路径:
/lib/
:存放系统启动时需要的基本库。/usr/lib/
:存放常用的 32 位和 64 位库。/usr/local/lib/
:手动安装或本地编译的软件库的默认路径。/lib64/
和/usr/lib64/
:对于 64 位系统,专门存放 64 位版本的库。
- 自定义路径:用户自定义或编译的库可能存放在
/opt/lib/
或特定项目的目录中。
3.3标准库
定义:标准库是编程语言中规定的一组函数和类,这些函数和类的接口(API)被标准化。例如:
- C语言的标准库包括
stdio.h
、stdlib.h
等,它们提供了基本的输入输出、内存管理等功能。 - C++ 标准库包括
iostream
、vector
、algorithm
等,用于提供面向对象的功能、容器、算法等。
标准库与动静态库的关系:标准库以静态库或动态库的形式存在
3.4动态库与静态库的标准库选择
- 一般情况下,操作系统和编译器会默认使用动态库版本的标准库,因为它更节省空间,并且允许系统中的所有程序共享同一份标准库代码。
- 在某些情况下,比如嵌入式系统或不希望依赖外部库的独立应用程序,开发者可以选择使用静态库版本的标准库,以确保程序能够在没有外部依赖的情况下运行。
4.gcc编译命令
$ gcc -E hello.c -o hello.i #预处理
$ gcc -S hello.i -o hello.s #编译
$ gcc -c hello.s -o hello.o #汇编
$ gcc hello.o -o hello #链接
$ gcc hello.c -o hello #直接编译链接成可执行目标文件
选项:
-o <filename>
:指定输出文件的名称。-E
:只执行预处理,不进行编译,输出预处理后的代码。-S
:只进行编译到汇编阶段,生成汇编代码(.s
文件)。-c
:只进行编译,不链接,生成目标文件(.o
文件)。-static
:强制进行静态链接,生成独立的可执行文件。-g
:生成调试信息,用于调试器(如gdb
)。
5.gcc编译多个源文件
# test.h
# test1.c
# test2.c
$ gcc test1.c test2.c -o test #不用写头文件,因为在同一个目录下,编译器会先在当前目录下寻找头文件