当你在IDE里创建了一个工程,写好了你的各个头文件和源文件,按下运行按钮时,发生了什么?

我们以C/C++程序为例,假如现在有一个工程test.pro,该工程中有源文件main.cpp、MyClass.cpp、MyClass2.cpp,头文件MyClass.h、MyClass2.h。

这是一个仅为了举例使用的简单工程,MyClass和MyClass2是两个什么功能都没写的类,主函数在main.cpp中,主函数中调用标准库函数printf输出字符串"Hello World!"。

#include <stdio.h>
#include "MyClass.h"
#include "MyClass2.h"int main(int argc, char *argv[])
{const char *p="Hello World!";printf("%s",p);return 0;
}

点击运行时,首先,你的源程序们会变成一个可执行程序,这个过程又可细分为四个阶段:预处理、编译、汇编、链接

预处理

C/C++的宏替换和文件包含的工作,不归入编译器的范围,而是交给独立的预处理器。主要处理源代码文件中的以“#”开头的预编译指令。处理规则为:

  • 1、删除所有的#define,展开所有的宏定义。
    (注:通过这一点我们可以看到#define和const定义常量的区别,#define所做的是在预处理阶段简单地做字符串替换,不会进行任何安全检查,而const定义常量,是编译器来处理,编译器会检查是否有语法错误,比较而言,const定义常量更加安全。)
  • 2、处理所有的条件预编译指令,如“#if”、“#endif”、“#ifdef”。
  • 3、处理“#include”预编译指令,将文件内容替换到它的位置。比如我们这个例子中的#include <stdio.h>命令,预处理器会读取系统头文件stdio.h的内容,并把它直接插入到程序文本中。
  • 4、删除所有的注释,“//”和“/**/”。
  • 5、保留所有的#pragma编译器指令,编译器需要用到他们,如:#pragma once 是为了防止有文件被重复引用。
  • 6、添加行号和文件标识,便于编译时编译器产生调试用的行号信息,编译时产生编译错误或警告能够显示行号。

.c和.cpp文件经过预处理后就变成了.i和.ii文件。

编译

把预处理之后生成的.i(C)或.ii(C++)文件,进行一系列词法分析、语法分析、语义分析及优化后,生成相应的汇编代码文件。

汇编

汇编器根据汇编指令和机器指令的对照表,将汇编代码一 一翻译成机器码。经汇编之后,产生可重定位的目标文件(与可执行文件格式几乎一样)xxx.o(Windows下)、xxx.obj(Linux下)。

我们来看看可重定位的目标文件格式,Windows使用的是PE(Portable Executable)格式,Linux和Unix系统使用的是ELF(Executable and Linkable Format)格式,不管是哪种格式,基本的概念是相似的。下图是ELF可重定位目标文件的格式,一个典型的ELF可重定位目标文件包含下面几个节:
       

链接(这里讲的链接,严格说应该叫静态链接。)

链接就是将工程中的多个可重定位目标文件组合成单一可执行文件的过程。在Windows系统下可执行文件的后缀是.exe,在Unix系统下是.out,由于我的计算机使用的Windows系统,最后生成的可执行文件是test.exe。

       

链接器必须完成两个任务:

  • 1、 符号解析:目标文件.o定义和引用符号,每个符号对应于一个函数、一个全局变量或一个静态变量,符号解析的目的是将每个符号引用和定义关联起来。
  • 2、 重定位:汇编器生成地址从0开始的可重定位目标文件,链接器通过把每个符号定义与一个内存位置关联起来,从而重定位这些节,然后修改所有对这些符号的引用,使得它们指向这个内存位置。

对每个可重定位目标文件而言,它们的代码、只读数据、全局变量、静态变量等的地址都是相对于本文件而言的。在例子中的main.o、MyClass.o、MyClass2.o,它们文件中的符号(函数、全局变量、静态变量)的地址都在本文件中定好了,链接器所做的工作就是把这些文件组合成一个文件,在组合的过程中,要把每个文件中的这些符号的地址修改一下,修改的规则如下图,EIF可重定位目标文件的每个节会被映射到可执行目标文件对应的节中。

源程序们经过预处理、编译、汇编、链接最终生成了一个可执行程序。其中,预处理器、编译器、汇编器、链接器一起构成了编译系统(简称编译器)。常见的编译系统有GCC、MSVC。

可执行程序是一个静态的概念,我们可以打开QQ安装目录看看QQ的可执行程序(应用程序),这个程序和我们电脑上运行着的QQ有什么关系呢?

程序保存在磁盘上,是静态的,你不去删除它它就一直都存在。运行着的QQ是一个进程,而进程运行在内存上,是动态的,你把运行着的QQ关了,那么这个进程就被操作系统回收了,这个进程就消亡了。


       一个工程中的源程序在点击运行后,会经历预处理、编译、汇编、链接生成可执行程序,可执行程序中的某些节再被加载到内存中,最终成为进程。

一个C/C++程序的一生:从源程序到可执行程序再到进程相关推荐

  1. 刷题一个4ms的程序,代码如何优化到3ms再到2ms?

    目录 前言 具体 结语 如果觉得本文有所帮助,记得点赞收藏! 前言 你在打王者荣耀的时候,是否经常会遇到这种情况:和对面同位置对线的时候,自己也没有太大失误,但是为啥对面经济比我高?能够压着我打?-- ...

  2. 应用FileInputStream类,编写应用程序,从磁盘上读取一个Java程序,并将源程序代码显示在屏幕上

    应用FileInputStream类,编写应用程序,从磁盘上读取一个Java程序,并将源程序代码显示在屏幕上. package p1;import java.io.*; public class FI ...

  3. Go程序的一生是怎样的?

    Go 程序是怎样跑起来的 原创: 饶全成 码农桃花源  刚开始写这篇文章的时候,目标非常大,想要探索 Go 程序的一生:编码.编译.汇编.链接.运行.退出.它的每一步具体如何进行,力图弄清 Go 程序 ...

  4. CSAPP——Hello程序的一生

    CSAPP大作业:程序人生-Hello's P2P 摘 要 程序的一生是怎样的?本篇论文将以hello.c程序为例,带你漫步程序的一生:预处理.编译.汇编.链接.运行和回收:带你结识程序一生中所邂逅的 ...

  5. 在纸上写好一个c语言程序后,上机运行的基本步骤为,c基本概念(选择题).docx

    PAGE / NUMPAGES 一.单选题 1.下面叙述中正确的是: (A) 在C语言程序中,main()函数必须放在程序的开始位置 (B) 在C语言程序中,要调用的函数必须在main()函数中定义 ...

  6. 一个C/C++程序从编译到最终生成可执行文件的全过程分析

    一个C/C++程序从编译到最终生成可执行文件的全过程分析 C源程序->编译预处理->编译->优化程序->汇编程序->链接程序->可执行文件  1.编译预处理  读取 ...

  7. 什么是Pro*C/C++,嵌入式SQL,第一个pro*c程序,pro*c++,Makefile,Proc增删改查

     1 什么是Pro*C/C++ 1.通过在过程编程语言C/C++中嵌入SQL语句而开发出的应用程序 2.什么是嵌入式SQL 1.在通用编程语言中使用的SQL称为嵌入式SQL 2.在SQL标准中定义 ...

  8. 【知乎】怎么成为一个优秀的程序员,而不是一个优秀的码农?

    怎么成为一个优秀的程序员,而不是一个优秀的码农? 9 条评论 分享 默认排序按时间排序 98 个回答 3844赞同反对,不会显示你的姓名 萧井陌 微信公众号:炼瓜研究所 技术社区 - 3844 人赞同 ...

  9. c语言作业答案第四章,C语言程序的设计课件源程序及习题的答案第4章.ppt

    C语言程序的设计课件源程序及习题的答案第4章 第4章循环结构的流程及应用 学习目标 ? 使用循环处理需要反复执行的操作. ? 循环结构的流程图. ? 循环与条件的综合应用. 学一学 while语句的一 ...

最新文章

  1. 重构第28 天 重命名bool方法(Rename boolean method)
  2. JDK 1.5 环境变量的配置
  3. 如何判断自己是否到了该辞职的时候
  4. 宁德时代拟定增募资不超582亿元,用于锂离子电池项目等
  5. Python IDLE换行写,一行写不下,如何换行继续写
  6. 最全最新个税计算公式---今天你税了吗?
  7. 初次尝试CE修改器修改小游戏
  8. 8.2.1 消息通知过时写法解决
  9. 杜比服务器网站,杜比服务器远程账号和密码
  10. 基于python pygame实现的雨点动画
  11. Python-数据类型转换
  12. excel提取每一行或每一列的最后一个数据
  13. (2012.12.25)我的中级软件设计师考试
  14. 私有云服务器搭建教程(保姆级)——台式电脑+ubuntu+docker+nextcloud+mysql+花生壳内网穿透
  15. android system w,Android system.err
  16. 心形公式表白(逼格更高一点哈哈哈)
  17. UE4移动组件详解(三)——RootMotion与特殊移动模式的实现思路
  18. 每日新闻:徐小平:硬科技仍处在学习阶段;微软发布会定档10月2日 以升级现有产品线为主...
  19. Tensorboard打开方式
  20. 【Quicker】您的指尖工具箱

热门文章

  1. 微信小程序循环赋值坑(转)
  2. react里面的楼梯效果
  3. 拓商:在拼多多开店,商家如何做好推广?
  4. 智慧职教云Java题库_云课堂智慧职教java职业证书题库答案
  5. 初级前端面试题 - js
  6. Visio 学习笔记 —— 链接线的默认样式
  7. js 年月日时分秒 格式转换成年月日格式
  8. 最新苹果CMS橙子仿B站自适应源码含教程
  9. a113 智能音箱芯片方案_收藏:10大芯片厂商,推出20款智能音箱解决方案
  10. 出现SLF4J: Failed to load class “org.slf4j.impl.StaticLoggerBinder“.的解决方法