当前位置: 首页 > 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.dtcms.com/a/321995.html

相关文章:

  • 第七篇:动画基础:requestAnimationFrame循环
  • 解决多线程安全性问题的方法
  • 可编辑51页PPT | 某鞋服品牌集团数字化转型项目建议书
  • 相机Camera日志实例分析之十:相机Camx【萌拍调节AE/AF拍照】单帧流程日志详解
  • 基于MATLAB实现的毫米波大规模MIMO系统中继混合预编码设计
  • [windows]torchsig 1.1.0 gr-spectrumdetect模块安装
  • LeetCode 刷题【34. 在排序数组中查找元素的第一个和最后一个位置、35. 搜索插入位置】
  • 哈希法(Java)
  • 【数据结构】排序(sort) -- 计数排序
  • wstool和git submodule优劣势对比
  • select ... for update阻塞
  • 【感知机】感知机(perceptron)学习算法例题及详解
  • 任务管理器如何查看详细的命令行和路径?
  • 安科瑞能源管理系统在某新材料公司光储充一体化项目上的应用
  • 【C++空指针革命】nullptr:告别NULL的终极解决方案与底层实现剖析
  • 在超算中心,除了立式机柜(rack-mounted)还有哪些形式?
  • 官方Windows系统部署下载工具实践指南
  • 遥测自跟踪天线系统组成、特点、功能、工作流程
  • 【普通地质学】地质年代与地层系统
  • 无人机SN模块运行与功能详解
  • Vibe coding现在能用于生产吗?
  • 什么是0.8米分辨率卫星影像数据?
  • C++ WonderTrader源码分析之自旋锁实现
  • nflsoi 8.8 题解
  • CF每日3题(1400-1700)
  • 第9章 AI 安全、可解释性与伦理合规
  • 3天落地企业级应用,JNPF+AI重塑开发效率
  • sqli-labs靶场less46-less50
  • 传送带包裹漏检率↓78%!陌讯动态感知模型在物流分拣的实战优化
  • dMSA 滥用 (BadSuccessor) 导致权限升级:使用 ADAudit Plus 监控关键属性更改