C编译与环境

 我们平时所说的程序,是指双击之后可以直接运行的程序,这样的程序被称为可执行程序(Executable Program),也就是windows平台下常见的.exe。本文就来说一说从你编写的代码到生成.exe,期间经历了什么以及相关知识。

    可执行程序的内部是一系列计算机指令和数据的集合,它们都是二进制形式的,CPU可以识别;但是对于写代码的人来说,它们非常隐晦且难以记忆。

    事实上在计算机发展的初期,人们就是用二进制指令来编写程序的,那个年代还没有编程语言。

    想象一下,程序员使用一长串01符号来编写程序,是不是感觉很崩溃。

    直接使用二进制指令编程简直是人的噩梦,特别是程序比较大的时候,不但编写麻烦,需要频繁查询指令手册,而且一旦出错,面对满满的0和1,会异常苦恼,眼花缭乱。

    因此,这逼着程序员开发出了编程语言,提高了生产力。如,汇编、C语言、C++、Java、Python等,都是在逐步提高开发效率。至此,编程不再是只有极少数人能够做的事情了,普通人经过一定的学习也可以编写出像样的程序。

    C语言代码由固定的词汇按照一定的格式组织起来,简单直观,程序员容易识别和理解,但是对于CPU,C语言就如同天书,根本不认识。CPU只认识一些二进制形式的指令。这时就需要一个工具,将C语言代码转换成CPU能够识别的二进制指令,也就是将代码加工成.exe程序的形式,这个工具是一个特殊的软件,我们称之为编译器(compiler)。而在认识编译器之前,我们得先了解一下环境。

扫描二维码关注公众号,回复: 8729860 查看本文章

环境

    在ANSI C的任何一种实现中,存在两种不同的环境。第一种是编译环境(开发环境),在这个环境中,源代码被转换为可执行的机器指令。第二种是运行环境(执行环境),它用于实际运行代码。标准中明确说明,这两种环境不必位于同一台机器上。例如,多平台的开发经常会涉及到一个词,交叉编译器(cross compiler),它就是在一种机器上运行,而它所产生的可执行代码可以运行在不同类型的机器上。硬件平台是如此,操作系统也是如此。事实上,在嵌入式系统的开发中,总是会遇到这种情况,你在pc机上编写代码,然后在pc机上通过交叉编译器生成对应各种芯片的可执行程序,将程序传输到芯片上去运行。

编译&链接

    编译器能够识别代码中的词汇、句子以及各种特定的格式,并将它们转换成计算机能够识别的二进制形式,这个过程称为编译。

1.编译

    编译过程本身也由几个阶段组成,组成一个程序的每个源文件通过编译过程各自分别转换为对应的目标代码(object code)

1.1预处理

    首先是预处理器(preprocessor)的预处理。这个阶段,预处理器在源代码中执行一些文本操作。例如,用实际值代替由#define指令定义的符号以及读入由#include指令包含的文件的内容。

1.2编译

    然后,经过预处理器替换后的代码就会进入到编译器(compiler)。这个阶段,源代码经过解析,根据规则判断各个语句的意思。这个阶段是我们平时编写代码的时候绝大多数错误和警告信息产生的地方。它是一个复杂的过程,期间涉及到各种复杂的算法和硬件架构。如果你是计算机相关专业的大学生,这方面的知识可以在"编译原理"这门专业课中学习到,大致分为下面几个步骤,这里不展开讲解。

语法分析: 分析表达式是否遵循语法规则

词法分析:分析关键字,标识符,立即数是否合法

语义分析:在语法分析基础上进一步分析表达式是否合法

    分析完成后,根据配置的代码优化生成相应的汇编代码文件。

    事实上,不了解编译原理并不影响学习编程语言,也不建议初学者去钻研编译原理。

1.3汇编

    接着,代码进入到汇编器(assembler),它将汇编代码转变成机器可执行的指令。一般而言,汇编器生成的是目标代码。

2.链接

    C代码经过编译以后,并没有生成最终的可执行文件,而是生成了目标文件的中间文件(临时文件)。

    而这时链接器(linker)将这些文件的目标代码捆绑链接最终才生成可执行文件。目标文件与可执行文件的格式其实是一样的,但是为什么还需要进行链接才能变成可执行文件呢?因为编译只是将我们自己写的代码变成了二进制形式,而它的运行还需要和系统组件结合起来,这些组件是程序运行所必须的。

    根据链接方式的不同,链接过程还可分为:

静态链接,目标文件直接进入可执行文件

动态链接,程序启动后才动态地加载目标文件

    现在如果你是C语言初学者,那可能没有涉及到这些知识,但是随着学习的深入,代码变多,甚至涉及到项目,那不太可能只有一个源文件。而工程中大量的源文件最终生成一个目标文件,就需要链接器将你多个源码的目标文件组合起来。

总结

无论你的代码多么简单,都必须经过编译、链接的过程才能生成可执行文件。

编译就是将编写的源代码"翻译"成机器可以识别的二进制代码,它们是以目标文件的形式存在。编译是针对单个源文件的。

链接是一个"打包"的过程,它将所有的目标文件以及系统组件组合成一个可执行文件。

一般来讲,我们所说的"编译器"实际上包含了预处理器、编译器、汇编器、链接器,这点上不必过分深究。

发布了60 篇原创文章 · 获赞 18 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/BadAyase/article/details/102458582