当前位置: 首页 > news >正文

C语言编译流程讲解

1、 预处理

1)预处理命令

在 C 语言的编译过程中,预处理是第一个阶段。它的主要任务是处理源代码文件中的预处理指令,将其转换为编译器可以识别的格式。

预处理主要包括以下几个方面:

  • 宏替换(例如 #define 定义的宏)
  • 文件包含(例如 #include 头文件)
  • 条件编译(例如 #if#ifdef 等)
  • 注释移除

预处理的结果是一个新的源代码文件,这个文件通常比原始文件要大,因为预处理器会展开宏、插入头文件的全部内容等。这一结果会保存在一个临时文件中,并作为后续编译器输入。

示例:对两个源文件进行预处理

使用如下命令进行预处理:

jimmy@ubuntu:~/helloworld$ gcc -E hello.c -o hello.i
jimmy@ubuntu:~/helloworld$ gcc -E main.c -o main.i

命令参数说明:

  • -EExpand(展开)的缩写,表示仅执行预处理阶段。

  • .iIntermediate(中间)的缩写,通常预处理生成的文件以 .i 作为后缀。

2、 编译

编译阶段,编译器会将预处理后的源代码文件(.i 文件)转换为 汇编代码(.s 文件)

这个过程包括以下几个步骤:

  • 词法分析
  • 语法分析
  • 语义分析
  • 代码优化

编译器会检查源代码的语法和语义,生成对应的汇编代码。这是整个编译过程中最复杂、最耗时的阶段之一,决定了程序的正确性和性能。

编译命令示例:

jimmy@ubuntu:~/helloworld$ gcc -S hello.i -o hello.s
jimmy@ubuntu:~/helloworld$ gcc -S main.i -o main.s

参数说明:

  • -S:**Source(源代码)**的缩写,表示只执行编译生成汇编代码。

  • .s:**Assembly Source(汇编源码)**的缩写,表示输出为汇编代码文件。

1.7.4 汇编

1)汇编命令

汇编阶段,由 汇编器(Assembler).s 汇编代码翻译成目标机器的二进制代码(.o 文件)。这是机器可以直接执行的指令格式,虽然尚未链接成最终程序。

汇编器的主要任务包括:

  • 符号解析

  • 指令翻译

  • 地址关联

  • 重定位处理

  • 简单的代码优化

汇编命令示例:


jimmy@ubuntu:~/helloworld$ gcc -c hello.s -o hello.o atguigu@ubuntu:~/helloworld$ gcc -c main.s -o main.o`

参数说明:

  • -cCompile or Assemble,表示将 .s.c 文件编译为目标文件(机器码),但不进行链接

  • -oObject 的缩写,表示输出的目标文件名,一般以 .o 为后缀。


2)目标文件内容结构分析

汇编完成后生成的 .o 文件是目标文件,可以使用 objdump 工具查看其内容。

查看机器码和反汇编:

objdump -d main.o

3)常见的 section(段)

目标文件中被划分为多个段(section),不同段的功能不同:

  • .text:包含可执行指令,是程序的主代码区。

  • .data:包含已初始化的全局变量和静态变量,这些变量在程序启动时已经被赋初值。

  • .bss:包含未初始化的全局变量和静态变量。不占用目标文件的实际空间,仅指示运行时要分配并清零的内存区域。

  • .rodata只读数据段,如字符串常量和其他只读常量。

  • .symtab.rel.text.debug_info 等其他段用于调试、符号表、重定位等目的。

1.7.5 链接

链接阶段由链接器完成,它将多个目标文件及所需库链接为最终的可执行文件。

链接器主要功能:

  • 解析符号引用与定义(如函数、全局变量)
  • 处理地址重定位
  • 合并各目标文件和库文件
  • 生成可执行程序或共享库文件

1)链接方式

(1)静态链接

将所有目标文件和库全部打包到一个可执行文件中,运行时不再依赖外部库。

gcc -static main.o hello.o -o main
# -static:强制使用静态库进行链接

(2)动态链接

程序运行时才加载库,减小体积,提升复用性。

方式一:默认动态链接

gcc main.o hello.o -o main # 不加 -static,默认使用动态链接

方式二:使用自定义动态库

生成动态库:

gcc -fPIC -shared -o libhello.so hello.o # -fPIC:生成位置无关代码 # -shared:生成共享库(.so)

链接生成可执行文件:

gcc main.o -L ./ -lhello -o main_d # -L ./:指定库路径 # -lhello:链接 libhello.so

-L ./表示额外的库文件位置为当前目录

运行时指定库路径:

LD_LIBRARY_PATH=./ ./main_d

(3)混合链接

部分库使用静态链接,其他使用动态链接。

生成静态库:

ar crv libhello.a hello.o

链接优先动态库(若存在):

gcc main.o -L ./ -lhello -o main

强制使用静态库(先删除 .so):

rm libhello.so

2)glibc 的库说明

  • 动态库路径:/usr/lib/x86_64-linux-gnu/libc.so

  • 静态库路径:/usr/lib/x86_64-linux-gnu/libc.a

http://www.lryc.cn/news/614682.html

相关文章:

  • 【Open3D】基础操作之三维数据结构的高效组织和管理
  • 内网穿透原理与部署实战指南:从理论到企业级应用
  • 第七章:数据持久化 —— `chrome.storage` 的记忆魔法
  • 2025 蓝桥杯C/C++国B 部分题解
  • 设计一个 Java 本地缓存组件
  • java分布式定时任务
  • 秋招笔记-8.8
  • BGP协议笔记
  • 6_基于深度学习的火灾检测识别系统(yolo11、yolov8、yolov5+UI界面+Python项目源码+模型+标注好的数据集)
  • 腾讯前端面试真题
  • 锯床自动长度检测与参数闭环补偿系统
  • 坚鹏:AI智能体辅导是知行学成为AI智能体创新应用引领者的保障
  • 计算机网络:到底什么是可变长子网掩码VLSM?
  • Linux初级阶段性练习
  • 移动端开发中类似腾讯Bugly的产品推荐与比较-5款APP异常最终产品推荐-卓伊凡|bigniu
  • A100用transformers推理gpt-oss
  • 第六章第四节 PWM驱动LED呼吸灯 PWM驱动舵机 PWM驱动直流电机
  • 校招秋招春招小米在线测评小米测评题库|测评解析和攻略|题库分享
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘huggingface_hub’问题
  • Numpy科学计算与数据分析:Numpy高效数据处理与优化
  • Mac 电脑放在环境变量中的通用脚本
  • 免费PDF批量加密工具
  • 从零掌握 Java AWT:原理、实战与性能优化
  • 【沉浸式解决问题】pycharm关闭科学模式
  • 杰理ac791 [Info]: [LL_S]Recv - LL_CHANNEL_MAP_REQ
  • Python从入门到精通计划Day07: Python数据卷轴术:文件魔法与防御结界全指南
  • nlp-语义分析
  • 在 Vue 中使用 ReconnectingWebSocket实现即时通讯聊天客服功能
  • Java 使用 SSHJ 执行 SSH 命令和 SFTP 文件上传和下载
  • 【前端后端部署】将前后端项目部署到云服务器