gcc/g++

编译器 gcc/g++

背景知识

编译过程分为四个阶段:

阶段 说明
1. 预处理 进行宏替换、去注释、条件编译、头文件展开等
2. 编译 生成汇编代码
3. 汇编 生成机器可识别代码(目标文件)
4. 链接 生成可执行文件或库文件

gcc 编译选项

基本格式

bash 复制代码
gcc [选项] 要编译的文件 [选项] [目标文件]

预处理(进行宏替换)

  • 功能:宏定义、文件包含、条件编译、去注释等
  • 说明 :预处理指令是以 # 号开头的代码行
  • 选项-E(让 gcc 在预处理结束后停止编译过程)
  • 输出文件.i 文件(已经过预处理的 C 原始程序)

示例

bash 复制代码
gcc -E hello.c -o hello.i

编译(生成汇编)

  • 功能:检查代码规范性和语法错误,将代码翻译成汇编语言
  • 选项-S(只进行编译而不进行汇编,生成汇编代码)
  • 输出文件.s 文件(汇编代码)

示例

bash 复制代码
gcc -S hello.i -o hello.s

汇编(生成机器可识别代码)

  • 功能 :将 .s 汇编文件转成目标文件(二进制目标代码)
  • 选项-c
  • 输出文件.o 文件(目标文件)

示例

bash 复制代码
gcc -c hello.s -o hello.o

链接(生成可执行文件或库文件)

  • 功能:将目标文件链接成可执行程序
  • 说明:成功编译后进入链接阶段

示例

bash 复制代码
gcc hello.o -o hello

动态链接和静态链接

在实际开发中,多个源文件之间存在依赖关系。每个 .c 文件独立编译成 .o 文件,为了满足依赖关系,需要将这些目标文件进行链接,形成可执行程序。

静态链接

缺点

  • 浪费空间 :多个程序对同一个目标文件有依赖时,每个可执行程序都含有一份副本(如多个程序都调用 printf(),则每个程序都包含 printf.o
  • 更新困难:库函数代码修改后,需要重新编译链接形成可执行程序

优点

  • 可执行程序中已具备所有执行所需的内容
  • 运行时速度快

动态链接

动态链接把程序按模块拆分成相对独立的部分,在程序运行时才将它们链接在一起,而不是像静态链接那样把所有模块都链接成一个单独的可执行文件。

查看可执行程序依赖的动态库

bash 复制代码
$ ldd hello
linux-vdso.so.1 => (0x00007fffeb1ab000)
libc.so.6 => /lib64/libc.so.6 (0x00007ff776af5000)
/lib64/ld-linux-x86-64.so.2 (0x00007ff776ec3000)

ldd 命令用于打印程序或者库文件所依赖的共享库列表。

库的概念

C 程序中的 printf 函数并没有在代码中定义实现,stdio.h 中也只有声明。实际实现被放在 libc.so.6 库文件中

在没有特别指定时,gcc 会到系统默认搜索路径 /usr/lib 下进行查找,链接到 libc.so.6 库函数,从而实现 printf 函数------这就是链接的作用。


静态库和动态库

类型 说明 后缀名 链接时机
静态库 编译链接时,把库文件的代码全部加入到可执行文件中,运行时不再需要库文件 .a 编译时
动态库 编译链接时不加入代码,程序执行时由运行时链接文件加载库 .so 运行时

注意事项

  • gcc 在编译时默认使用动态库
  • 可以使用 file 命令验证生成的二进制程序是否为动态链接

示例

bash 复制代码
gcc hello.o -o hello   # 默认动态链接

gcc 其他常用选项(了解即可)

选项 说明
-E 只激活预处理,不生成文件,需要重定向到输出文件
-S 编译到汇编语言,不进行汇编和链接
-c 编译到目标代码(.o 文件)
-o 文件输出到指定文件
-static 对生成的文件采用静态链接
-g 生成调试信息,GNU 调试器(gdb)可利用该信息
-shared 尽量使用动态库,生成文件较小,但需要系统提供动态库
-O0 优化级别 0:不进行优化
-O1 优化级别 1:缺省值(默认级别)
-O2 优化级别 2
-O3 优化级别 3:优化级别最高
-w 不生成任何警告信息
-Wall 生成所有警告信息

说明-O0-O1-O2-O3 是编译器的优化选项的 4 个级别,-O0 表示没有优化,-O1 为缺省值,-O3 优化级别最高。

相关推荐
倔强的石头10623 分钟前
【Linux指南】动静态库系列(二):从源码复用到目标文件复用:为什么需要把 .o 打包成库
linux·运维·服务器
HLC++13 小时前
Linux的进程间通信
android·linux·服务器
华清远见IT开放实验室14 小时前
实验室建设案例 | 石家庄科技信息职业学院嵌入式实验室——从底层硬件到系统应用,一所应用型高校的嵌入式人才培养这样落地
linux·arm开发·stm32·嵌入式硬件·高校·实验室建设
groundhappy16 小时前
idalib安装和codex ida-mcp配置
linux·开发语言·python
通信小小昕17 小时前
Ubuntu 26.04 中文输入法安装
linux·运维·ubuntu
张小姐的猫18 小时前
【Linux】网络编程 —— HTTP协议(上)
linux·运维·服务器·网络·http·单例模式·策略模式
栩栩云生19 小时前
AI 写代码犯的错,早被写进了错题集
linux·安全·ai编程
imc.1120 小时前
linux基础IO
linux·运维·服务器
BelongPanda1 天前
Linux Nginx 纯手动 Let‘s Encrypt 泛域名证书配置教程
linux·nginx
酷可达拉斯1 天前
Linux操作系统-shell编程(0)
linux·运维·服务器·python·云计算