c++ 从编译到执行
看别人的博客上拼出答案.不会就先模仿吧.
这个是今日头条面试时候的一个题目,当时别提答的多烂了,感觉一个题目准备深了还是非常耗费时间的.小论文一样.c/c++从编译到执行要经历以下过程:
源代码-->预处理-->编译-->优化-->汇编-->链接-->目标程序
我们先来敲一个hello.cpp 吧.
#include<stdio.h>
int main()
{
printf("Hello world\n");
return 0;
}
预处理过程
要进行第一步,预处理过程,要干的事情有哪些呢, 要处理预编处理宏定义,条件编译指令,条件包含指令,特殊符号.
对于宏定义指令,会将宏定义变量替换成对应的部分.对条件编译指令,预处理过程按照程序定义过滤掉不必要的部分. 对条件包含指令,预编译程序会把它通通加入到目标文件当中. 对于一些特殊符号,预编译程序会识别出来并用合适的值替换.
综合来说实际上就是一个替换的动作,处理哪些带#符号的命令和一些特殊符号.
我们如何得到这个文件呢,linux可以敲下面的命令:
gcc -E hello.cpp hw.i
得到预处理之后的文件.
编译过程
词法分析,语法分析,在确定所有的指令都符合语法规则后,将其翻译成目标代码,最终目标文件是目标代码.
在编译的过程中,所有的变量都是虚拟地址.在汇编文件中有一个表,存储了虚拟地址对应的变量名称.
直接 g++ -S hello.i -o hello.s
优化过程
优化处理是编译系统中一项比较艰深的技术。它涉及到的问题不仅同编译技术本身有关,而且同机器的硬件环境也有很大的关系。优化一部分是对中间代码的优化。这种优化不依赖于具体的计算机。另一种优化则主要针对目标代码的生成而进行的。上图中,我们将优化阶段放在编译程序的后面,这是一种比较笼统的表示。
对于前一种优化,主要的工作是删除公共表达式、循环优化(代码外提、强度削弱、变换循环控制条件、已知量的合并等)、复写传播,以及无用赋值的删除,等等。
后一种类型的优化同机器的硬件结构密切相关,最主要的是考虑是如何充分利用机器的各个硬件寄存器存放的有关变量的值,以减少对于内存的访问次数。另外,如何根据机器硬件执行指令的特点(如流水线、RISC、CISC、VLIW等)而对指令进行一些调整使目标代码比较短,执行的效率比较高,也是一个重要的研究课题。
经过优化得到的汇编代码必须经过汇编程序的汇编转换成相应的机器指令,方可能被机器执行。
汇编过程
经历汇编过程编译转换成机器码,最终形成与源程序等效的机器码.目标文件由段组成. 通常一个目标文件至少有两个段
代码段和数据段.代码段包含了可读可执行的程序的指令. 数据段保存各种全局变量和静态的数据.一般数据段可读可写可执行.
gcc -c hello.c -o hello.o 这里的hello.o就是最后的机器码.作为一个静态库的话可以说已经完成了,不需要后面的流程.
UNIX环境下主要有三种类型的目标文件:
(1)可重定位文件 其中包含有适合于其它目标文件链接来创建一个可执行的或者共享的目标文件的代码和数据。
(2)共享的目标文件 这种文件存放了适合于在两种上下文里链接的代码和数据。第一种事链接程序可把它与其它可重定位文件及共享的目标文件一起处理来创建另一个目标文件;第二种是动态链接程序将它与另一个可执行文件及其它的共享目标文件结合到一起,创建一个进程映象。
(3)可执行文件 它包含了一个可以被操作系统创建一个进程来执行之的文件。
汇编程序生成的实际上是第一种类型的目标文件。对于后两种还需要其他的一些处理方能得到,这个就是链接程序的工作了。
链接程序
由汇编程序生成的目标文件并不能立即就被执行,其中可能还有许多没有解决的问题。例如,某个源文件中的函数可能引用了另一个源文件中定义的某个符号(如变量或者函数调用等);在程序中可能调用了某个库文件中的函数,等等。所有的这些问题,都需要经链接程序的处理方能得以解决。
链接程序的主要工作就是将有关的目标文件彼此相连接,也即将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,使得所有的这些目标文件成为一个能够诶操作系统装入执行的统一整体。
根据开发人员指定的同库函数的链接方式的不同,链接处理可分为两种:
(1)静态链接 在这种链接方式下,函数的代码将从其所在地静态链接库中被拷贝到最终的可执行程序中。这样该程序在被执行时这些代码将被装入到该进程的虚拟地址空间中。静态链接库实际上是一个目标文件的集合,其中的每个文件含有库中的一个或者一组相关函数的代码。(个人备注:静态链接将链接库的代码复制到可执行程序中,使得可执行程序体积变大)
(2)动态链接 在此种方式下,函数的代码被放到称作是动态链接库或共享对象的某个目标文件中。链接程序此时所作的只是在最终的可执行程序中记录下共享对象的名字以及其它少量的登记信息。在此可执行文件被执行时,动态链接库的全部内容将被映射到运行时相应进程的虚地址空间。动态链接程序将根据可执行程序中记录的信息找到相应的函数代码。(个人备注:动态链接指的是需要链接的代码放到一个共享对象中,共享对象映射到进程虚地址空间,链接程序记录可执行程序将来需要用的代码信息,根据这些信息迅速定位相应的代码片段。)
对于可执行文件中的函数调用,可分别采用动态链接或静态链接的方法。使用动态链接能够使最终的可执行文件比较短小,并且当共享对象被多个进程使用时能节约一些内存,因为在内存中只需要保存一份此共享对象的代码。但并不是使用动态链接就一定比使用静态链接要优越。在某些情况下动态链接可能带来一些性能上损害。
经过上述五个过程,C源程序就最终被转换成可执行文件了。缺省情况下这个可执行文件的名字被命名为a.out。
关于动态链接库与静态链接库的创建与区别可以看下这篇博文
c++ 从编译到执行的更多相关文章
- 关于JavaScript预编译和执行顺序以及函数引用类型的思考
昨晚在对项目中的一部分做模块化处理的时候,遇到了一个问题,一个重新定义的function对一个通用类中的function进行赋值覆盖的时候,失败了.问题抽象出来是这样的: <script > ...
- java在cmd下编译和执行引用jar的类
java编译和执行引用第三方jarcmd 1.将上面的ojdbc14.jar文件,与调用程序复制到系统D盘的根目录下,切记:因为调用程序在wym.database包下,所以需要将类其所在的包一起拷贝 ...
- JS的预编译和执行顺序 详析(及全局与局部变量)
最近在复习javascript的事件处理时发现了一个问题,于是总结一下:javascript的预编译和执行顺序的问题: <html> <head> <title> ...
- 如何用javac 和java 编译运行整个Java工程 (转载)【转】在Linux下编译与执行Java程序
如何用javac 和java 编译运行整个Java工程 (转载) http://blog.csdn.net/huagong_adu/article/details/6929817 [转]在Linux ...
- Java 代码编译和执行的整个过程
Java 代码编译是由 Java 源码编译器来完成,流程图如下所示: Java 字节码的执行是由 JVM 执行引擎来完成,流程图如下所示: Java 代码编译和执行的整个过程包含了以下三个重要的机制: ...
- 如何确定C#代码是在编译时执行还是在运行时执行
突然想起那个"switch..case..."的case标签都可以判断哪些类型... 就先搞了一个错误的demo... class Program { static void Ma ...
- 在CMD窗口中使用javac和java命令进行编译和执行带有包名的具有继承关系的类
一.背景 最近在使用记事本编写带有包名并且有继承关系的java代码并运行时发现出现了很多错误,经过努力一一被解决,今天我们来看一下会遇见哪些问题,并给出解决办法. 二.测试过程 1.父类代码 pack ...
- 在windows下使用cmd命令行对java文件进行编译和执行
windows下利用cmd命令行可以调用jdk里的javac.exe和java.exe对java文件进行编译和执行,前提是jdk已成功安装并正确配置相关环境变量 相关配置链接:java基础学习总结—— ...
- JVM学习笔记(二)------Java代码编译和执行的整个过程【转】
转自:http://blog.csdn.net/cutesource/article/details/5904542 版权声明:本文为博主原创文章,未经博主允许不得转载. Java代码编译是由Java ...
- php脚本的执行过程(编译与执行相分离)
php脚本的执行过程(编译与执行相分离) 深入理解PHP代码的执行的过程 PHP程序的执行流程 Apache + PHP 的并发访问
随机推荐
- Vue前后端分离实现登录的一个简单demo
1.建立一个Maven项目,并添加Spring相关依赖 2.编写Controller类相应的接口和配置类 LoginController类,编写接口的业务逻辑 package com.springbo ...
- [OpenCV实战]24 使用OpenCV进行曝光融合
目录 1 什么是曝光融合 2 曝光融合的原理 3 代码与结果 4 参考 本教程中,我们将了解使用OpenCV的Exposure Fusion(曝光融合). 1 什么是曝光融合 曝光融合是一种将使用不同 ...
- [OpenCV实战]7 使用YOLOv3和OpenCV进行基于深度学习的目标检测
目录 1 YOLO介绍 1.1 YOLOv3原理 1.2 为什么要将OpenCV用于YOLO? 1.3 在Darknet和OpenCV上对YOLOv3进行速度测试 2 使用YOLOv3进行对象检测(C ...
- 如何使用Redis和RabbitMQ实现一个学生抢课系统(可类比商品秒杀系统)
1.如何使用Redis和RabbitMQ实现一个学生抢课系统(可类比商品秒杀系统) 电商项目中的秒杀场景我们都很常见,不只是京东和淘宝现在很多的小程序公众号也有做现时限购的秒杀场景,那么如何做一个秒杀 ...
- python进阶之路9文件的处理方法
内容回顾 字典内置方法 1.类型转换 dict() 2.重要操作 get() d[key] = values 常用 pop() update() 键存在则修改键值对 键不存在则新增键值对 fromke ...
- 《深度探索C++对象模型》第四章 Function语意学
member function相对于nonmember function之间不存在效率之间的差别,因为编译器内部已经将"member 函数实体"转化为对等的"nonmem ...
- Ubuntu 安装 SSH
sudo apt install openssh-server sudo systemctl status ssh sudo ufw allow ssh
- 使用iframe引入文件后设置响应式宽高以及其他问题解决;
第一 :引入iframe后背景色解决: 需要先设置 被引入文件的body样式 第二:滚动以及其他样式需要设置,span是为了小屏准备的,处理小屏时候元素距离顶部高度问题: 这个是span 的样式 然后 ...
- 【Azure Cache for Redis】Python Djange-Redis连接Azure Redis服务遇上(104, 'Connection reset by peer')
问题描述 使用Python连接Azure Redis服务,因为在代码中使用的是Djange-redis组件,所以通过如下的配置连接到Azure Redis服务: CACHES = { "de ...
- python正则查找
a = "#1+#5+#8+#10+#11+#12+#13+#14+#15-#22-#23-#24-#25-#26-#27-#28" b = re.findall("#\ ...