当前位置: 首页 > 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.xdnf.cn/news/1263727.html

相关文章:

  • centos出现ping: baidu.com: 未知的名称或服务问题
  • DMETL简单介绍、安装部署和入门尝试
  • nflsoi 8.8 题解
  • Linux 内核发包流程与路由控制实战
  • 用 “故事 + 价值观” 快速建立 IP 信任感
  • 亚马逊广告运营如何平衡ASIN投放和关键词投放
  • Chrome DevTools Protocol 开启协议监视器
  • C/C++与JavaScript的WebAssembly协作开发指南
  • Vue框架总结案例
  • 机器学习-----SVM(支持向量机)算法简介
  • PEV2(PostgreSQL Explain Visualizer 2)
  • 「安全发」ISV对接支付宝+小猎系统
  • DataFun联合开源AllData社区和开源Gravitino社区将在8月9日相聚数据治理峰会论坛
  • Blob File Buffer ArrayBuffer uint8Array DataView 的关联
  • 使用pytest对接口进行自动化测试
  • 5. 缓存-Redis
  • Java文件操作与IO流核心技术解析
  • 【matlab】采样信号的低通滤波、高通滤波
  • PeiQi网络安全知识文库PeiQi-WIKI-Book保姆式搭建部署教程
  • 【探展WAIC】从“眼见为虚”到“AI识真”:如何用大模型筑造多模态鉴伪盾牌
  • PyQt简介
  • 本地开发penpot源码支持AI原型设计(一)
  • 深圳市天正达电子股份有限公司参展AUTO TECH China 2025 广州国际汽车技术展览会
  • 【感知机】感知机(perceptron)学习算法知识点汇总
  • 使用pybind11封装C++API
  • 智能体协同作战:实现工具调用成功率提升47%的架构奥秘
  • C语言学习笔记——编译和链接
  • 知识图谱【2】
  • 任务管理器如何查看详细的命令行和路径?
  • 塔罗耳语:免费在线AI塔罗牌占卜工具