gcc的使用

gcc的使用

目录

  1. 什么是gcc
  2. gcc编译过程
  3. 函数库
    1. 静态库
    2. 动态库
    3. 标准库
    4. 动态库与静态库的标准库选择
  4. gcc编译命令
  5. 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编译过程

  1. 预处理
    • 功能:预处理器处理以 # 开头的指令,进行代码的预处理。
    • 主要任务
      • 宏替换:处理 #define 指令,将宏替换为其对应的值。
      • 文件包含:处理 #include 指令,替换为所包含文件的内容。
      • 条件编译:处理条件编译指令,如 #ifdef#ifndef#endif,决定哪些代码片段应该被包含或排除。
    • 输出:生成一个扩展后的 C 源文件(通常以 .i 后缀),所有的宏和包含文件已被处理,结果是一个“干净”的源代码文件。
  2. 编译
    • 功能:将预处理后的源代码转换为汇编语言。
    • 主要任务
      • 语法分析:分析代码的语法结构,构建语法树,检查语法错误。
      • 语义分析:检查代码的语义正确性,如变量类型和作用域,确保变量在使用前已定义。
      • 优化:根据编译器的设置进行一些基本优化,以提高生成代码的效率。
    • 输出:生成一个汇编语言文件(通常以 .s 后缀),包含对应于源代码的汇编指令。
  3. 汇编
    • 功能:将汇编语言代码转换为机器语言,生成目标文件。
    • 主要任务
      • 翻译指令:将汇编语言的指令翻译为对应的机器语言指令。
      • 生成符号表:记录代码中使用的变量和函数名及其地址,供链接器使用。
      • 处理数据段:分配内存空间以存储变量和常量,生成数据段和代码段。
    • 输出:生成一个目标文件(通常以 .o 后缀),其中包含机器代码和符号信息,但还不是可执行文件。
  4. 链接
    • 功能:将一个或多个目标文件和库文件合并,生成最终的可执行文件。
    • 主要任务
      • 符号解析:解析各个目标文件中的符号,将其地址绑定到具体的内存地址。
      • 地址重定位:调整代码和数据段中的地址引用,以确保它们在最终可执行文件中是正确的。
      • 合并段:将不同目标文件的代码和数据段合并为一个整体,生成可执行文件。
      • 库链接:将所需的库(如标准库)链接到可执行文件中,确保程序能够调用库中的函数。
    • 输出:生成一个可执行文件,用户可以直接运行。

3.函数库

  1. 在链接时,库链接链接的库就是函数库。
  2. 我们在C语言中调用的printf函数,在头文件stdio.h中只有声明,没有实现。
  3. 类似printf的实现,都被放在了函数库里

概念函数库是指一些预定义的、可重用的函数集合,开发人员可以直接调用这些函数,而不必重新编写代码。函数库是程序开发的重要组成部分,帮助提高代码的效率和可维护性。根据库的链接方式,将函数库分为静态库动态库

3.1静态库

  • 静态库在编译时被链接到可执行文件中。
  • 编译后的可执行文件包含所有使用到的库代码,因此可执行文件相对较大。
  • 一旦编译完成,静态库就不需要在运行时存在。
  • 静态库的文件扩展名通常是:
    • 在 Linux 系统中为 .a
    • 在 Windows 系统中为 .lib

优点:无需依赖外部库文件,适合独立运行的程序。

缺点:可执行文件体积较大,库的更新需要重新编译。

Linux下常见存放位置

  • 系统级库路径
    • /usr/lib/:大多数系统库的存放位置,适用于 32 位和 64 位库。
    • /usr/local/lib/:手动安装或本地编译的软件库的默认路径。
    • /lib/:一些系统关键的静态库也可能存放在这里。
  • 自定义路径:如果你编译或安装了自定义库,静态库可能存放在自定义路径,比如 /opt/lib/ 或用户自定义的目录下。

3.2动态库

  • 动态库在运行时动态加载,并不会在编译时直接链接到可执行文件中。
  • 动态库可以被多个程序共享,因此可执行文件体积较小。
  • 运行时,操作系统会寻找并加载动态库
  • 动态库的文件扩展名通常是:
    • 在 Linux 系统中为 .so(共享对象)
    • 在 Windows 系统中为 .dll(动态链接库)

优点

  • 可执行文件体积小,库更新方便(无需重新编译可执行文件)。
  • 允许多个程序共享相同的库资源。

缺点:程序运行时依赖于外部库文件,若找不到对应的库,程序将无法运行。

Linux下常见存放位置

  • 系统级库路径
    • /lib/:存放系统启动时需要的基本库。
    • /usr/lib/:存放常用的 32 位和 64 位库。
    • /usr/local/lib/:手动安装或本地编译的软件库的默认路径。
    • /lib64//usr/lib64/:对于 64 位系统,专门存放 64 位版本的库。
  • 自定义路径:用户自定义或编译的库可能存放在 /opt/lib/ 或特定项目的目录中。

3.3标准库

定义标准库是编程语言中规定的一组函数和类,这些函数和类的接口(API)被标准化。例如:

  • C语言的标准库包括 stdio.hstdlib.h 等,它们提供了基本的输入输出、内存管理等功能。
  • C++ 标准库包括 iostreamvectoralgorithm 等,用于提供面向对象的功能、容器、算法等。

标准库动静态库的关系:标准库以静态库或动态库的形式存在

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	#不用写头文件,因为在同一个目录下,编译器会先在当前目录下寻找头文件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值