IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 程序是如何被编译的?以gcc为例 -> 正文阅读

[C++知识库]程序是如何被编译的?以gcc为例

编译过程

? 对于一个C/C++程序来说,在编写完代码之后到运行之间,需要完成编译的过程。我一直对这个过程有很多疑问,今天整理一下这个编译的大概流程。

选择一个编译器

? 计算机只能运行二进制代码,一个信息的组成,由信息本身的二进制串和解释方式构成。

? 我们需要将高级语言的代码,通过编译器编译成二进制代码之后,交给CPU进行解码和处理。这个编译的过程需要软件来进行,这种软件就是编译器

? 常用的C/C++编译器有,GCC,g++,clang等。基于Linux使用的常见的是GCC编译器,这篇文章也是基于这个编译器进行的

? 首先介绍一下GCC的基本使用方式:

? GCC编译器是通过shell的方式进行使用的(就是在内个黑框框里面)。大概的格式是:

gcc [参数] [代码文件]

? 常见的参数有:

-E //进行预处理
-S //进行编译而不进行汇编和链接
-o //将文件输出到指定的文件里面(可以理解为,重命名)
-c //编译和汇编,但是不链接

? 这些参数大家也许现在不知道是干什么的,一会会结合例子讲解的

编译流程

? 我们选择好一个编译器之后,接下来就是进行正式的编译了。

? 我们基于单个文件的编译过程:

拥有一个c文件

? 让我们先拥有一个c文件:main.c

#include<stdio.h>
#define MAX 100
int main(void){
    int i=MAX;
    printf("HelloWorld\n");
    return 0;
 }

? ok,这是最简单的c语言程序了。

编译的具体流程

GCC编译经过四个阶段:

预处理,编译,汇编,链接

我们一步一步的来:

预处理阶段:

? 预处理阶段可以理解为:文本处理的阶段。我们写过C语言的都知道,C语言中有宏这个说法,比如:

#define MAX 100

? 这个以#开头的东西,就是宏定义,预处理阶段要完成的第一件事就是宏展开,将所有的宏替换。比如对于上面内个例子,预处理阶段就会把所有的MAX替换为100

? 预处理阶段还完成了另一见事情,对于#include<...>这些语句的意思是将某个头文件引入,预处理阶段就会将这些引入的头文件也展开,导入我们的main.c文件当中

? 我们使用GCC进行第一步的处理:

gcc -E main.c -o main.i

? 得到的.i文件就是预处理后的代码文本了,我们用vim来看一下main.i中都有什么

?

? 大家如果熟悉stdio.h的话,这些函数就是定义在其中的内容,可以看到预处理确实是将头文件中的内容加入到了我们自己编写的c文件了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ivm7LdL2-1656325117873)(编译过程.assets/tmp1FC.png)]

? 这里可以看到我们使用的printf函数了

在这里插入图片描述

? 在.i文件的最下方我们找到了main.c的内容,我们可以发现,int i=MAX已经被替换为了int i=100,这就是进行了宏展开的过程。

在这里插入图片描述

编译阶段

? 在预处理阶段得到展开后的代码文本后,接下来我们就要正式开始将高级语言的代码向机器语言进行翻译了

? 这个翻译不是一蹴而就的,我们经过了这样的步骤:

C/C++
汇编语言
机器语言

? 编译阶段进行的就是将C/C++翻译为汇编语言的过程

? 我们使用GCC:

gcc -S main.i -o main.s

? main.s文件就是翻译后的汇编语言文件

? 同样的,使用vim查看一下main.s的内容

在这里插入图片描述

? 可以看到翻译后的main函数

汇编阶段

? 汇编阶段就要将汇编文件,转换为目标文件:

? 什么是目标文件?Linux当中的.o文件,在Windows’系统下则为.obj文件,其实就是二进制文件,是未经过链接阶段的二进制文件

? 这里就简单的记住,目标文件就是二进制文件,但是没有经过链接过程

? 我们使用GCC

gcc -c main.s -o main.o
//注意使用-c,-c的意思是,编译和汇编,但是不链接

强行vim打开,发现很多奇怪的字符,但可以看到ELF这几个字母,这是一种文件格式,我们之后会讲到

在这里插入图片描述

链接阶段

? 到这里,二进制目标文件已经产生,接下来就要进行连接。

? 可是,什么是连接?为什么要进行连接呢?

? 我们用一个例子来解释一下这个问题:

假设,现在有三个文件,a.c,b.hb.c,其内容为:

//a.c
#include"b.h"
int main(void){
    func();
}
//b.h
#ifndef BH
#define BH
void func();
#endif
//b.c
#include<stdio.h>
#include"b.h"
void func(){
    ;
}

得到这些文件之后,我们编译a.c得到它的目标文件

gcc -c a.c -o a.o

然后,使用

readelf -s a.o

查看目标文件中的符号表

新的问题产生了,什么是符号表?通俗点来说,符号,就是函数和变量,符号表,就是一个表格,其中记录着符号的各种信息

那么未经过连接的a.o的符号表是什么样子的呢?

在这里插入图片描述

其他信息我们不关注,注意看第十一行:func前面的UND,就是undefined,虽然gcc编译了a.c,但是它并不知到func到底是个什么东西,因为,func的实现在b.c里面

我们再编译一下b.c吧:

gcc -c b.c -o b.o

在这里插入图片描述

看第十行,func前不是UND而是1,因此说明了,func是存在于b.c中的

那么解决方法就很自然了:既然a的符号在b中,那么就把a,b合并了不就行了

因此:

ld a.o b.o -e main -o main

这句的意思是,链接a.o和b.o,入口函数是main函数,链接后文件名为 main

readelf -s main

这样一来,就链接上了,func符号也存在,也不是UND了

在这里插入图片描述

反汇编看一下:

objdump -d a.o

未链接前的a.o:

? 在这里插入图片描述

objdump -d main

在这里插入图片描述

注意看callq的那一行。最开始因为无法定位到func具体位置,因此编译器在a.o中定位在00 00 00 00

在main中,则是找到了具体的位置,偏移量未00 00 00 07

401012+00 00 00 07=401019,也就是func的位置。

? 好,回答main.c,使用gcc进行链接:

gcc main.o -o main

然后运行

./main

在这里插入图片描述

运行出了结果

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-07-04 22:37:15  更:2022-07-04 22:40:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/12 10:59:38-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码