程序编译和链接的过程

马谦马谦马谦
马谦马谦马谦
马谦马谦马谦
605
文章
12
评论
2018年9月14日23:08:41 评论

一、概述

一个程序在从源码变成二进制程序之间一共有四个步骤:预处理,编译,生成目标文件,链接。

以下展示了一个简单的加法程序的编译过程:

二、预处理

预处理阶段主要有以下的操作:

  • 头文件替换
  • 宏定义替换
  • 删除注释
  • 预处理指令处理

在GCC中,-E选项用于预处理,执行g++ main.cpp -E -o main.i

可以看到,main.i的内容已经变得十分复杂,预处理后总共有接近两万行。

文件的后就是我们的实际代码区域,其中的头文件和注释也都被处理掉了。

三、编译

预处理完成后需要编译,编译是把程序编程汇编指令的过程。在这一阶段会分析代码,解析语法和错误。

-S选项用用于生成汇编指令,生成后它依旧还是一个文本文件,执行g++ main.i -S main.s后的main.s中的内容:

程序编译和链接的过程

四、生成目标文件

目标文件也就是我们所说的.o文件了,在编译过后,文件还是不能直接被运行的。生成目标文件的过程会导出属于自己的符号表。这个步骤之后它就已经是一个二进制文件了,里面的符号可以通过诸如readelf的命令来读取出来。

生成目标文件的选项是-c,执行g++ main.s -c main.o

实际上,如果不经过前面的两个步骤,直接对源文件使用-c也能直接生成目标文件,编译器会自动执行中间的步骤:

五、链接

链接过程将把多个文件之间的符号表结合起来,生成最终的可执行文件。

 

历史上的今天
九月
14
马谦马谦马谦
  • 本文由 发表于 2018年9月14日23:08:41
  • 转载请务必保留本文链接:https://www.dyxmq.cn/program/code/c-cpp/program-compilation-and-linking-process.html
给socket分配随机端口 C/C++

给socket分配随机端口

客户端的socket不需要手动执行bind绑定地址,但这不意味着客户端socket真的不需要绑定端口,实际上是内核它帮我们做了这个操作,在执行connect时,内核发现没有绑定端口,就会自动选择一个合...
vector中emplace_back方法的用途 C/C++

vector中emplace_back方法的用途

在写代码的过程中,CLion提醒我把push_back方法替换成emplace_back方法: 代码中我的想法是使用vector创建一个二维数组,并提前分配好空间,避免后序频繁扩容增加时间复杂度。 e...
宏定义踩坑实战:嵌套调用宏定义 C/C++

宏定义踩坑实战:嵌套调用宏定义

问题背景:在刷题的过程中,要使用min函数,但是线上OJ并没有这个函数。因为一时也想不起它到底属于哪个头文件,所以为了偷懒,顺手就写下了以下宏定义: #define min(x, y) (x) <...
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: