每天学一点系列~“Hello World“的诞生

Posted 白龙码~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了每天学一点系列~“Hello World“的诞生相关的知识,希望对你有一定的参考价值。


Part I、熟悉的"Hello World"

相信每个程序员接触到的第一个程序就是将"Hello World"输出到屏幕上,随着学习的慢慢深入,屏幕上输出的东西越来越丰富多彩;可这个时候为什么又要回到一开始的"Hello World"呢?这样的重蹈覆辙有必要吗?

我们不妨先看看下面的这几个问题(出自《程序员的自我修养——链接、装载与库》)
1、程序为什么要被编译器编译了之后才能运行?
2、编译器在把C语言转换成机器代码的过程中到底发生了什么?
3、#include<stdio.h>又是什么意思?

如果以上的这些问题你都清清楚楚,那么我说:大佬!多有叨扰。
如果你不是特别清楚,那么这篇文章可能会成为带你初步认识编译"Hello World"的世界!

Part II、翻译环境及翻译过程简介

翻译环境,即用于开发应用程序的IDE(集成开发环境);

我们往往在IDE上创建一个.c或.cpp文件并编写相应的代码,然后单击运行,文件夹中就会多出一个.exe文件,然而事实上,在.c/.cpp和.exe文件中间还有几种格式的文件,每个文件的形成对应了一个过程,包括:预编译(预处理)、编译、汇编、链接。

经过这些过程,一段代码才被真正翻译成机器语言并具有被运行的功能。

下面我们对以上的几个过程进行一个详细的解读。

Part III、预编译

预编译,又叫预处理;我们在C语言的学习过程中接触过不少的预处理指令,而在预编译这一过程中就是进行预处理指令的执行,包括:

一、#系列指令

1、#define定义的宏和符号的展开和替换
2、#include头文件的包含(头文件中包括我们调用的库函数的信息)
3、#ifdef / #ifndef / #endif 等预处理指令的执行
宏和相关介绍可以参见这篇文章

二、删除注释

预处理的过程中会将我们写的所有注释进行删除

三、添加行号和文件名标识

添加行号和文件名标识以便于调试以及编译报错

预编译的过程主要进行的是文本的替换、增添与删除,并在.c文件的基础上生成.i文件

Part IV、编译

编译的简要过程为:词法分析和符号汇总→语法分析→语义分析→转汇编

一、词法分析和符号汇总

在这一过程中,源代码程序被输入到扫描程序(扫描器)中,扫描器根据构词规则识别单词,并将识别的符号(变量名等)进行一个简单的符号汇总工作

二、语法分析

这一过程在词法分析的基础上将单词组合成语句和表达式,判断程序在结构上是否正确

三、语义分析

这一过程对结构上正确的源程序进行类型和类型相关性质的审查,并执行类型转换等操作,对类型不匹配现象进行警告和报错

四、转汇编

对源代码进行优化并最终转为汇编语言

编译的过程主要进行语言标准方面的检查,并进行转汇编,在.i文件的基础上生成.s文件

Part V、汇编

一、形成符号表

符号表主要包括函数和变量名及其对应的地址等信息

二、转机器语言

将汇编代码最终转换为电脑可执行的机器语言

汇编过程在.s文件的基础上生成.o文件(windows系统下为.obj文件)

Part VI、链接

在介绍链接之前,我们先来看一个图:

从图中我们可以看出,对于.i、.s、.o文件的生成是相对独立的;编译器对每一个.c源文件单独处理,形成多个目标文件(.o文件),最终将所有的目标文件和链接库进行链接,形成可执行的文件。
链接过程如下:

一、将代码段(程序指令)和数据段(程序数据)进行段合并

二、将符号表进行合并和重定位

每一个.c源文件都能在编译过程中形成一张符号表,但对于有的符号表来说,它的内容是不完整的;
比如说,我们在一个.c文件中定义了一个函数,在主函数所在的文件中声明并使用了这个函数,但是由于函数的定义不在主函数所在文件,所以主函数所在文件形成的符号表中,调用函数的地址是未知的(临时被记为0x00);经过链接后,所有文件的符号表会进行合并,而那些临时的地址会被重定位成新的地址;

我们可以把这个过程看为拼拼图;每个目标文件都是一块拼图,而链接的过程就是将这些碎片拼成一整块图形的过程!

Part VII、系列文章索引

【每天学一点系列~】看得见摸不着的“隐式类型转换”
【每天学一点系列~】诡异的死循环
【每天学一点系列~】字符串左/右旋的本质,你真的认清了嘛?
【每天学一点系列~】这些内存函数你知道么?还记得么[\\doge]
【每天学一点系列~】一文带你彻底弄懂结构体大小和内存对齐

创作不易,给个三连呗亲!

以上是关于每天学一点系列~“Hello World“的诞生的主要内容,如果未能解决你的问题,请参考以下文章

每天学一点系列~字符串左/右旋的本质,你真的认清了嘛?

每天学一点系列~看得见摸不着的“隐式类型转换”

每天学一点系列~这些内存函数你知道么?还记得么[doge]

每天学一点系列~一文带你彻底弄懂结构体大小和内存对齐

Python每天学一点之argparse

每天学一点系列~还在困惑数据结构(尤其是链表)里指针的看这里!!!