• 忘掉天地
  • 仿佛也想不起自己
bingliaolongBingliaolong  2020-03-21 09:24 Aet 隐藏边栏 |   抢沙发  10 
文章评分 2 次,平均分 5.0

gcc/g++介绍

概述

  1. gccg++都是GNU(组织)的一个编译器

区别

  1. 后缀为.c的文件gcc把它当做c程序,g++当做c++程序。
  2. 后缀为c++的两者都当做c++程序。

其他

  1. 对于cpp程序,无论gcc或者是g++编译阶段都是相同的
    1. 都是用的gcc进行编译
    2. 但是在链接阶段gcc不能自动和c++程序使用的库连接
      如果使用的话,形如下: gcc helloworld.cpp -lstdc++ -o helloworld
  2. 所以我们通常用g++来进行连接(g++会自动连接c++常用库),所以为了使用方便对于cpp程序干脆编译链接统统都使用g++
    1. 这样就给人一种错觉,好像cpp只能用g++编译

gcc/g++作用

  1. C/C++源代码编译成机器可识别的指令

gcc/g++编译过程

  1. 预处理
    1. 在预处理阶段,编译器处理源代码中的预处理指令(以 # 开头的指令),包括宏定义、文件包含和条件编译等
    2. gcc -E test.c -o test.i  产生一个预处理后的文件( .i文件 )

  1. 编译

    1. 在编译阶段,编译器将预处理后的源代码翻译成汇编代码
    2. 具体如下:
    3. 语法分析:检查源代码的语法是否合法,构建抽象语法树(AST
    4. 语义分析:检查语义错误(例如,类型检查、作用域解析等)
    5. 中间代码生成:将源代码翻译成一种中间表示(如三地址码)
    6. 优化:对中间代码进行优化,以提高生成代码的效率
    7. 汇编代码生成:将中间代码翻译成目标机器的汇编代码
    8. gcc -S test.i -o test.s  产生一个汇编程序文件( .s文件 )
  2. 汇编

    1. 在汇编阶段,汇编器将汇编代码翻译成机器代码(二进制指令),生成目标文件
    2. 主要任务如下:
    3. 翻译汇编代码:将汇编代码中的每条指令翻译成对应的机器指令
    4. 符号解析:解析汇编代码中的符号,并为每个符号分配内存地址
    5. 生成目标文件:将机器代码和符号表打包成目标文件
    6. gcc -c test.s -o test.o  产生一个目标文件( .o文件)
  3. 链接

    1. 在链接阶段,链接器将多个目标文件(包括程序的目标文件和库文件)合并成一个可执行文件,解析符号引用,并处理重定位
    2. 主要任务如下:
    3. 符号解析:解析并匹配所有目标文件中的符号引用,确保每个符号都有定义
    4. 重定位:调整代码和数据地址,以便在可执行文件中正确运行
    5. 生成可执行文件:将所有目标文件和库文件合并,生成最终的可执行文件
    6. gcc test.o -o test    产生一个可执行文件

gcc/g++编译器常用选项

  1. 基本选项

    1. -c  只生成目标文件(.o文件),不链接
    2. -E  只进行预处理,不编译,生成预处理后的(.i)文件
    3. -S  生成汇编文件(.s)文件
    4. -o  指定输出的可执行文件名称
  2. 警告选项

    1. -Wall  给出所有有用的警告信息,有利于排查问题
    2. -Werror 在发生警告时取消编译操作,即将警报看作是错误
    3. -w  禁止警告,有时会隐藏程序中的错误
    4. -W  给出额外更详细的警告
  3. 优化选项

    1. -IdirectoryGCC的头文件搜索路径中添加新的目录
    2. -LdirectoryGCC的库文件搜索路径中添加一个行的目录
    3. -llibrary 提示连接程序在创建可执行文件时包含指定的库文件
    4. -static 强制使用静态库
    5. -shared 强制使用共享库
  4. 其他选项

    1. -xlanguage 指定输入文件的编程语言
    2. -v 显示编译器的版本号
    3. -g 获得有关调试程序的详细信息
    4. -ansi 支持符合ansi彼岸准的c程序

静态库/动态库

  1. linux系统中静态库的扩展名为.a,动态库的扩展名是.so
  2. 静态库是在每个程序进行链接的时候将库在目标程序中进行一次拷贝,当目标程序生成的时候,程序可以脱离库文件单独运行,换言之原来的文件即使删除程序还是会正常工作
  3. 共享库可以被多个应用程序共享,实在程序运行的时候进行动态的加载,因此对于每个应用程序来说,即使不再使用某个共享库,也不应该将其删除,因为其他的引用程序可能需要这个库

示例

  1. 预处理
    1. $ gcc -E hello.c -o hello.i
  2. 编译
    1. $ gcc -S hello.i -o hello.s
  3. 汇编
    1. $ gcc -c hello.s -o hello.o
  4. 链接
    1. $ gcc hello.o -o hello

本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

bingliaolong
Bingliaolong 关注:0    粉丝:0 最后编辑于:2024-07-15
Everything will be better.

发表评论

表情 格式 链接 私密 签到
扫一扫二维码分享