必威体育Betway必威体育官网
当前位置:首页 > IT技术

对于编译原理的理解

时间:2019-10-24 09:43:23来源:IT技术作者:seo实验室小编阅读:88次「手机版」
 

编译原理

#编译原理

今天组长教育了一下整个程序的编译过程,感觉自己对于这块了解还是很少,有许多知识之前知道,现在忘记了,还有很多规则只是知道,但并不知道它为什么要这样写,所以再次记录一下,有什么问题或者错误希望大家在评论区提出。。。。

编译原理

如图

这里写图片描述

预编译阶段

在预编译阶段,发挥作用的是预处理器(CPP)。预处理器读取.cpp文件,对其中的伪指令(#开头的指令)和特殊符号进行处理,特别的,对#include指令进行递归处理,包含需要的头文件。

常见的伪指令有#define、#include""(包括你需要的头文件),在你的预处理器处理过后,会将你#include的头文件中的代码内容(不包括预处理的内容)替换到你的.cpp文件中,也会将你#define的内容替换,会选择你条件编译(#if #else #endif)的代码块等汇总成一个新的源文件

预处理阶段还会将注释删除

添加行号和文件名标识,方便调试使用

特例:保留所有的#pragma指令,因为编译器需要使用

此时源程序还是文本文件。

###编译阶段

在这个阶段中,编译器(CC1)会进行语法分析、语义分析、词法分析、优化、将源文件转换为汇编语言,汇编语言还是文本文件,但cpu无法理解文本文件。

###汇编阶段

在这个阶段,发挥作用的是汇编器(AS),汇编器会将汇编语言翻译成机器语言,机器只会识别二进制,所以机器语言为二进制。window平台上是.obj文件,linux是.o文件,为可重定位的目标文件。

###链接阶段

这个阶段发挥作用的是连接器(LD),链接器会将所有的.obj文件链接到一起,成为可执行的.exe文件。链接时会将程序引用的库与自己生成的.obj文件一起链接成为可执行文件,这样的链接方式就叫做静态链接。但是存在一个问题,如果你的应用程序使用了很多库,静态链接会将所有的库链接到你的.obj文件中,最终形成很大的.exe程序,不利于以后程序的更新。所以就出现了动态链接。

动态链接,动态库在链接阶段不会被链接到.obj文件中,应该只是(我也不确定)将你用到的API的地址等一系列信息和你的.obj文件链接起来,形成.exe文件,在你的exe程序运行时才加载这个动态库文件,这样,就大大减少了你的应用程序的大小,方便更新等一系列优点。

###生成exe

这样,你的exe就生成了。

##注意点

###防止多重包含

在预处理阶段,你会经常看到#ifndef #define #endif。这是为了防止重复包含。在预处理器第一次处理这个头文件时,会#define一个宏,当其他文件再次包含这个头文件时,预处理器检测到这个宏,会直接跳过这段代码,这样就不会出现重复代码

###.h和.cpp文件

在编译成.obj文件时,一个.h和对应的.cpp会形成一个.obj文件,你的工程中如果有多个.h和.cpp文件,就会生成多个.obj文件,例如一个C_Object类的.h和.cpp文件将会生成一个.obj文件,此时已经成为机器语言的.obj文件,将会在链接时将会链接到一起生成可执行文件。

###例子

a.h

#ifndef A_H //防止多重包含
#define A_H
class C_A 
{
pulic:
	void funA();
};
#endif//A_H

a.cpp

#include<iOStream>
#include"a.h"
#include "global.h"

void C_A::funA()
{
  i=0;
  std::cout <<i <<std::endl;
}

b.h文件

#ifndef B_H
#define B_H
class C_B
{
public:
	void funB();
};
#endif // B_H

b.cpp文件

#include<iostream>
#include"global.h"
#include"b.h"
void C_B::funB()
{
 i=1;
 std::cout << i << std::endl;
}

global.h文件

#ifndef GLOBAL_H
#define GLOBAL_H
extern int i;
#endif //GLOBAL_H

global.cpp文件

int i ;//申请内存

main.cpp文件

#include"a.h"
#include"b.h"

void main()
{
C_A a;
C_B b;
a.funA();
b.funB();
}

程序很简单,但是如果我要注释掉extern int i;IDE会报什么样的错误呢?

我们推断一下,首先在预处理阶段不会报错,三个cpp文件会将他们包含的头文件的代码部分在分别的.cpp文件展开,成为新的文本文件。

在编译阶段也不会出错,因为没有语法错误,新的源文件会被编译成汇编语言,此时还是一个文本文件,此时应该还定义了程序中的变量应该申请多少内存,在程序运行时向系统索要内存。

在汇编阶段将会转化为a.obj、b.obj、gobal.obj,main.obj,此时为二进制,为机器语言。

链接阶段,应该为将四个文件链接到一起,a.obj中包括一个整形的i被定义,b.obj中也有一个i被定义,global.obj也有一个i被定义,链接到一起时检测到多个相同名称的变量存在,出错!报错为找到一个或多个多重符号的定义。所以要在global.h文件中声明i,这样连接器检测到i为一个声明,在不同的obj文件中进行赋值。通过编译。

那在global.h文件中声明一个函数,在.cpp文件实现,编译器会不会说函数多重定义呢?答案是不会,因为函数声明和定义的方式不一样,而变量的声明和定义如果不加extern关键字则会一样,无法辨别变量是声明还是定义,所以要有extern的存在。

文章最后发布于: 2018-03-15 20:42:31

相关阅读

条件编译

条件编译https://baike.baidu.com/item/条件编译/7692959#ifndefhttps://baike.baidu.com/item/%23ifndef/2835043?fr=aladdin

TCP三次握手,四次握手过程原理

为什么TCP要进行三次握手 在谢希仁着“计算机网络”第四版中讲“三次握手”的目的是“ 为了防止已失效的连接请求报文段突然又传

Java程序运行堆栈原理

Java程序运行原理分析 Java程序运行流程 Java程序运行原理分析----环境介绍 从最初的jdk安装开始,都是程序运行的关键步骤,每

三个原理,激发你源源不断的创意

如何提升创意,又如何才能获得源源不断的创意?笔者针对这个问题,总结了大脑的三个功能引发创新的原理,enjoy~广告人:这个广告创意,我为什

解释百度排名点击器原理与制作

作为网站管理员,无论是个人站,还是企业站,甚至是门户站,最担心的无非就是不被搜索引擎所收录,在引擎里面得不到关键词相应的排名;然后,

分享到:

栏目导航

推荐阅读

热门阅读