gcc原理和使用

gcc

gcc是什么

GCC,全称 GNU Compiler Collection(GNU 编译器套件),是一套功能强大的编程语言编译器,由自由软件基金会(Free Software Foundation, FSF)作为GNU项目的一部分开发和维护。它最初被创建为一个C语言编译器,后来扩展支持了C++,以及随着时间的推移增加了对其他编程语言的支持,如Fortran、Ada、Java、Go和Rust等。

主要特点与功能

  1. 多语言支持

    • GCC最初是作为C编译器开发的,因此得名GNU C Compiler。
    • 随后增加了对C++(称为G++)、Fortran、Ada等多种语言的支持。
  2. 跨平台编译

    • GCC可以用于多种操作系统平台,包括Linux、Windows、macOS等。
    • 它能够生成跨平台的代码,使得编写的程序能在不同的系统架构上运行。
  3. 优化能力

    • 提供多种级别的优化选项,帮助开发者提升程序的执行效率。
    • 优化选项包括但不限于代码大小优化、执行速度优化等。
  4. 标准遵循与兼容性

    • GCC严格遵循各种编程语言的标准,例如ISO C++和ISO C标准。
    • 不断更新以支持最新的语言标凈。
  5. 调试和错误报告

    • 提供详细的错误和警告信息,帮助开发者快速定位问题。
    • 与GDB(GNU Debugger)等调试工具配合良好,提供强大的调试支持。
  6. 可扩展性

    • 开放源代码,允许开发者自定义或扩展编译器的功能。
    • 支持插件,可用于增强编译过程或添加新的功能。

应用场景

GCC广泛应用于软件开发和系统编程领域,特别是在开源项目和Linux系统开发中。它是许多Linux发行版默认的编译器,用于编译Linux内核、GNU操作系统和其他大量的应用程序。

安装与使用

  • 在Linux系统中,GCC通常可以通过包管理器(如apt、yum等)安装。
  • 在Windows上,GCC可以通过MinGW(Minimalist GNU for Windows)或Cygwin等工具获得。
  • 在macOS上,可以通过Homebrew或Xcode的命令行工具来安装GCC。

GCC不仅仅是一个编译器,它还是一个强大的工具,对于软件开发和计算机科学教育来说至关重要。由于其开源和免费的特性,GCC对编程社区的贡献不可估量,是推动软件创新和教育普及的重要工具。

c11需要gcc版本 > 4.8.5

查看版本

gcc -v
image-20240417191223707

gcc工作流程

image-20240417191520664

GCC(GNU Compiler Collection)的工作流程涵盖了将源代码转换为可执行文件的多个阶段。这些阶段依次是预处理、编译、汇编和链接,每个阶段都承担着特定的任务,共同完成从源代码到可执行程序的转换。

  1. 预处理阶段(Preprocessing)
  • 任务:预处理器处理源代码文件中以#开头的指令。这包括宏定义的展开、文件包含指令的处理(如#include)、条件编译指令(如#ifdef, #ifndef, #endif)的处理等。
  • 结果:输出的结果是“展开”的源代码,已经插入了所有包含的文件内容,展开了所有宏定义,移除了所有条件不满足的代码块,此外还处理了编译器指令和特定的注释等。
  1. 编译阶段(Compilation)
  • 任务:编译器将预处理后的源代码转换成汇编语言。在这个阶段,编译器进行词法分析、语法分析、语义分析和优化。编译器检查代码的语法错误,分析变量和函数的使用情况,以及执行代码优化以提高程序的运行效率和减少内存占用。
  • 结果:生成的是汇编语言代码,对应于平台的机器指令集。
  1. 汇编阶段(Assembly)
  • 任务:汇编器将汇编语言转换为机器语言,生成目标代码。汇编语言是一种低级语言,比源代码更接近于机器代码,但仍然是人类可读的格式。
  • 结果:输出的是目标文件(通常是.o.obj文件),这些文件包含了机器语言代码但尚未解析外部引用。
  1. 链接阶段(Linking)
  • 任务:链接器处理一个或多个目标文件,并将它们与库(可能是动态的或静态的)合并,解析外部引用,生成最终的可执行文件。在这个阶段,链接器也处理符号解析、地址和偏移量分配等任务。
  • 结果:生成的是可执行文件(在Unix-like系统中通常无扩展名,在Windows中为.exe文件),这些文件包含了可以被操作系统载入内存并执行的所有机器指令。

示例

假设你有一个名为hello.c的C语言程序,整个GCC编译和链接的命令行可以简化为:

gcc -o hello hello.c

这条命令会自动执行上述所有阶段,从hello.c生成可执行文件hello。如果你想观察或控制中间过程,可以使用额外的GCC选项来单独执行各个阶段,例如:

gcc -E hello.c -o hello.i   # 只运行预处理,输出预处理后的文件hello.i
gcc -S hello.c              # 生成汇编代码hello.s
gcc -c hello.c              # 生成目标文件hello.o
gcc hello.o -o hello        # 将目标文件链接成最终的可执行文件

GCC的这种工作流程允许开发者对编译过程有更细致的控制,同时也支持跨平台开发,因为GCC可用于多种操作系统平台上。

gcc常用参数选项

GCC(GNU Compiler Collection)提供了许多命令行参数,这些参数允许开发者定制编译过程、优化生成的代码、指定特定的编译器行为等。下面列出了一些GCC中最常用的参数选项:

基本编译选项

  • -c

    • 编译源代码到目标文件,不进行链接。
    • 例如:gcc -c program.c 生成 program.o
  • -o output

    • 指定生成的输出文件的名称。
    • 例如:gcc program.c -o program 生成一个名为 program 的可执行文件。
  • -g

    • 生成调试信息,方便使用GDB等调试工具进行调试。
    • 例如:gcc -g program.c -o program

优化选项

  • -O, -O1, -O2, -O3

    • 设置优化级别:
      • -O0(默认):不进行优化。
      • -O1:进行基本优化。
      • -O2:进行进一步优化,包括增加编译时间的优化。
      • -O3:启用更多的优化,包括 -O2 所有的优化以及一些额外的优化来提升性能。
    • 例如:gcc -O2 program.c -o program
  • -Os

    • 优化生成的代码,使其占用的空间尽可能小。
    • 例如:gcc -Os program.c -o program

警告控制选项

  • -Wall

    • 开启几乎所有的警告信息。
    • 例如:gcc -Wall program.c -o program
  • -Wextra

    • 开启额外的警告信息,比 -Wall 更严格。
    • 例如:gcc -Wall -Wextra program.c -o program

链接选项

  • -l

    • 链接时指定库名。
    • 例如:gcc program.c -lm -o program 链接数学库 libm
  • -L

    • 指定库文件搜索路径。
    • 例如:gcc program.c -L/home/user/mylibs -lm -o program

预处理选项

  • -Dmacro

    • 定义宏。
    • 例如:gcc -DDEBUG program.c -o program 在编译时定义 DEBUG 宏。
  • -I

    • 指定包含文件(头文件)的搜索路径。
    • 例如:gcc -I/home/user/myheaders program.c -o program

其他有用的选项

  • -std=cXX

    • 指定使用特定的C语言标准进行编译,如 c99c11c17 等。
    • 例如:gcc -std=c11 program.c -o program 使用C11标准编译。
  • -pedantic

    • 要求GCC严格遵守ISO C和ISO C++标准,禁用非标准扩展。
    • 例如:gcc -pedantic program.c -o program
  • -s

    • 在生成最终的可执行文件时去除所有符号信息,用于减少可执行文件的大小。
    • 例如:gcc -s program.c -o program

这些选项只是GCC提供的众多参数中的一部分,但它们是最常用的一些,覆盖了大部分常规需求。你可以结合使用这些选项来控制GCC的行为,优化程序的性能,或者调整程序的编译过程。要了解更多详细的编译选项,可以查阅GCC官方文档或使用 man gcc 命令获取帮助。

image-20240417192648646 image-20240417200507644
gcc test.c -E -o test.i
#include <stdio.h>


int main() {
    int a = 10;
#ifdef DEBUG
    printf("我是一个dccc\n");
#endif
    for (int i = 0; i < 3; i++) {
        printf("hello gcc\n");
    }
    return 0;
}
daic@daic:~/Linux/lesson03$ gcc test.c -o test -D DEBUG
daic@daic:~/Linux/lesson03$ ./test 
我是一个dccc
hello gcc
hello gcc
hello gcc
daic@daic:~/Linux/lesson03$ gcc test.c -o test -D DEBUG -Wall
test.c: In function ‘main’:
test.c:5:9: warning: unused variable ‘a’ [-Wunused-variable]
     int a = 10;
         ^

gcc和g++区别

GCC(GNU Compiler Collection)包含了多个前端编译器,用于处理不同编程语言的编译任务。gccg++ 是这个集合中最常用的两个命令,它们分别用于编译C和C++程序。虽然这两个工具在很多方面相似,但它们在处理C和C++代码时有一些关键的区别和特定的用法。

1. 基本区别

  • gcc

    • 通常用于编译C程序。
    • 默认情况下,它将用作C编译器。
    • 如果没有特别指定,它将尝试以C语言的标准来编译源代码文件。
  • g++

    • 专门用于编译C++程序。
    • 自动将C++库链接到程序中,包括标准模板库(STL)。
    • 默认情况下,将用作C++编译器。
  1. 链接库的不同
  • 当编译C++程序时,g++ 会自动链接C++标准库(如libstdc++)。这意味着使用g++编译器,用户不需要显式指定运行时库,而使用gcc编译C++程序时,可能需要手动添加 -lstdc++ 选项来链接C++库。
  1. 处理C++的特性
  • g++对C++的支持更全面,包括对模板的处理以及C++的名称修饰(name mangling)。这些特性在用gcc编译C++代码时可能不会完全支持,或者需要额外的参数来正确处理。
  1. 文件扩展名的敏感性
  • gcc根据文件扩展名判断如何编译文件。例如,它会将.c文件视为C程序,.cpp.cc文件视为C++程序。根据文件类型的不同,gcc可能需要指定语言标准来正确编译。
  • g++默认将所有文件视为C++文件,除非另有指定。
  1. 编译C文件的行为
  • 你可以使用g++来编译C文件。在这种情况下,g++将C代码视为C++代码的一部分,这通常是安全的,因为C是C++的一个子集。然而,某些严格的C代码在C++编译器下可能会因为语法或语义差异而出现编译错误。

示例

  • 使用gcc编译C++代码时需要链接C++库:

    gcc some_code.cpp -lstdc++ -o some_code
    
  • 使用g++编译相同的C++代码,不需要手动链接C++库:

    g++ some_code.cpp -o some_code
    

结论

虽然gccg++都是GCC的一部分,并且都可以用来编译C和C++代码,但是它们在默认行为和链接库方面有所不同。一般来说,推荐使用g++编译C++代码,而gcc则用于C代码,这样可以确保编译过程的顺利进行和程序的正确链接。

使用gcc和make调试程序的原理涉及到编译、链接和调试几个关键步骤。以下是大致的调试程序的原理: 1. 编写源代码:首先需要编写源代码,使用C或C++等编程语言编写程序。 2. 编译源代码:使用gcc编译器将源代码编译成可执行文件。编译过程中会将源代码转换为机器代码,并生成目标文件。 3. 链接目标文件:链接器将目标文件和系统库文件进行链接,生成最终的可执行文件。在链接过程中会解析函数引用、地址重定向等操作。 4. 添加调试信息:通过在编译时添加调试信息选项,如-g参数,可以在可执行文件中包含调试符号表和源代码映射关系。 5. 使用调试器:使用调试器,如gdb,加载可执行文件,并设置断点或其他调试指令。调试器提供了一系列工具和命令,可以单步执行程序、查看变量值、检查堆栈等。 6. 调试过程:在调试过程中,可以通过断点来暂停程序的执行,并逐步跟踪代码。可以观察变量的值、检查函数调用和返回,以及查看程序的状态。 7. 调试输出:在调试过程中,可以使用调试器提供的输出功能,如打印变量的值、显示调试信息等。 8. 修复问题:根据调试过程中的观察和分析,可以定位和修复程序中的问题,如逻辑错误、内存泄漏等。 9. 重新编译和调试:在修复问题后,可以重新编译程序,并使用调试器再次进行调试,以确认问题是否已解决。 总体来说,使用gcc和make调试程序的原理是通过编译、链接和使用调试器来定位和修复代码中的问题。调试器提供了一系列功能和命令,帮助开发人员探查程序的执行情况,以解决bug和改进代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值