源代码的翻译简介
我们知道机器其实是比较笨的,它只认识0101这样的机器语言.你用高级语言写的源代码对机器来说就像地球人看火星文一样,没法整明白的.必须要经过中间很多翻译环节.通常来说分为如下四步,实际上每一步都相当于在做翻译中的一小部分工作.
1.预编译阶段,也叫预处理.顾名思义就是在处理之前预先做些准备工作.比如你写的#include #define这样的预编译指令,还有一些注释,编译器可不认识.你得先用个预处理器把它们翻译下,让编译器可以认识才行.比如把注释去掉.把#include这样的标志也去掉,替换成引用的头文件的实际内容.
2.编译阶段.经过预处理后的源码,编译器就做啥词法分析,语法分析,如果它觉得老兄你写的代码错的有点太离谱就给个error,如果觉得源码虽然不太规范,但还不是太不靠谱就只给个warning.经过分析没有error的话最终会被翻译成等价的汇编语言.
3.汇编阶段.把第2步产生的汇编代码再翻译成0101这样的机器语言.
4.链接阶段.可能你写的代码并不是编译汇编成某一个文件,可能分散在不同的文件中.所以需要把它们链接到一起.成了最终的可执行文件,你双击下就可以运行了.这一步最终产生一个成品,前面三步产生的只是半成品.
注意事项.实际上只是便于理解像上面这样划分.虽然有时确实严格按上面四步,每一步有相应的工具来做那些工作.但有时并没有严格像上面这样按4步,但大概思想差不多.
1.)比如像C#,它没有像C++一样有一个独立的预处理器来做预处理阶段的工作,而是由编译器一起做了.实际上我们可以把上面4步全部用一个工具(编译器)做了,而不用分成4步然后用4个工具来做
2.)实际上严格来说,第4步产生了可执行文件,变成了机器能识别的机器语言就真的意味着机器能认识了.这时的可执行文件还是要基于操作系统的,只有依托于操作系统才能运行.实际上你可这样想,操作系统把底层硬件做了一个抽象.操作系统与底层硬件一起组成了一个抽象的"机器",你最终的代码能被这个"机器"识别
3.)实际上你还可以在操作系统上面再抽象一层,抽象出一个"机器",比如C#最终翻译成MSIL(微软中间语言),也是二进制串,但真正的机器可不认识.只有CLR这个"机器"能认识.另外像html标识语言,它翻译后也只有浏览器这个"机器"可以认识
不过为了便于理解,我们还是按上面说的4个步骤来分析下每一步具体做了些啥工作.先来说第一步预编译
预编译(或者说预处理)
预编译能做的事主要是下面4项
1.通过#include从其他文件里复制源程序正文来替换.我们在C++经常用它来引用头文件啊
2.通过#define定义宏,可以简单的把宏理解为把一长串字符ABC用一个很短的字符A来在代码中代替.然后预编译时又把所有的A替换回去,变成ABC.
3.条件编译,通过#define和#ifdef配合使用,把代码中不符合条件的代码块在预编译阶段全部删除掉.
4.用#progma以某种与实现有关的方式影响编译过程.比如有些警告信息你看着不顺眼,就可以通过#progma让编译器不再显示那警告信息
#include是C++中特有的,头文件也是C++中的概念.而头文件和#include在C#中没有了.那你肯定会有点迷糊,头文件起啥作用的?为啥C#中会没有?
C++头文件作用,为什么C#不需要头文件.
C++头文件作用
C++中的头文件自然是有些好处,可以很清晰的通过看一个头文件而知道一个类里面有啥成员变量和成员函数.然后可以通过引用一个头文件来使用其他类中的public成员和函数.不过其实头文件跟我们用define定义宏一样,只是方便我们而出现的.在预编译阶段全部被替换成了头文件中的实际内容.所以编译器编译的时候根本不会知道有头文件这东东存在.只有一个个的CPP文件.
在C++中,假如有有类Arwen需要用到类ABC的信息,Arwen中有函数Fun(),那必须在Arwen中用#include "ABC.h" 这样来引用头文件, 然后预编译的时候把#include "ABC.h"这一串给去掉.替换成文件ABC.h中的实际内容.比如void Fun();这些信息啊.然后呢接下来就是编译了,编译器就看你用到ABC的信息时是不是与ABC的声明吻合.例如你用ABC.Fun();函数时编译器一看Fun函数在声明中有就OK,但如果用ABC.Test();一看声明中没有,于是报错.
class ABC
{
public: void Fun();
};
类Arwen没预编译之前是下面这样
#include "ABC.h"
class Arwen
{
void CallFun() { ABC abc; abc.Fun(); }
}
预编译之后
class ABC
{
public: void Fun();
};
class Arwen
{
void CallFun() { ABC abc; abc.Fun(); }
}
C#不需要头文件的原因
namespace MyZone
{
class ABC {public Fun() { } }
}
namespace MyZone
{
classArwen {
public CallFun() {ABC abc = new ABC(); abc.Fun(); }
}
}
假如在C#,然后有类Arwen,需要用到类ABC的信息.可C#没有头文件的概念,在Arwen中用到ABC时咋整啊? C#的原理是这样的,编译的时候是先生成一些元数据(metadata),元数据里面有名称空间信息,然后每个名称空间(namespace)下面有些啥类,类的访问限制,类中有些啥字段,方法等(字段与方法等同于C++中的成员变量和成员函数).有了这些信息后编译器就可以靠这些信息判断你调用其他类时是否正确.像上面Arwen与ABC都在命名空间MyZone下面.编译器检查abc.Fun()调用正确不,会去元数据中查找MyZone下面跟类ABC相关信息.
但如果ABC如类Arwen不在同一个namespace中的话就得在Arwen前面用using ABCnamceSpace; 引用一个命名空间.实际上这和C++中用#include引用头文件的思想有点类似.C#是用using 引用命名空间.因为默认情况下编译器只会去检查与当前类相同命名空间的所有类信息.只有你用using显式引用了其他命名空间时才会也去检查那些命名空间下的类信息.
一般情况下一个项目就对应一个dll,与C++中的dll不同,C#的dll包含的信息更多
,所有元数据都在dll中.而一般一个项目中也只用到一个命名空间.当然我说的是一般,实际上一个dll中可以有多个命名空间, 或者多个dll是同一个命名空间. dll是实际存在的文件.命名空间是一个抽象的概念性的东西.
分享到:
相关推荐
这是对C/C++代码 封装 可以用C#调用。事实上,C系列中还存在一种语言叫做托管C++,这种语言语法上和C++几乎一样,但是却和C#一样编译成为微软中间语言,这样就可以和C#良好地通信,即可以在c#中使用托管C++类
C#调用C++编译的DLL详解
把C#编译成DLL或者Axtive控件,再由C调用!比如使用C++调用C#的DLL。 SwfDotNet是.net下输出flash的类库。SwfDotNet是C#编写的,作者的C#水平,真是令我佩服。这是个特别好的读写Swf文件的库。但是,我要用在C++项目...
提示:加了壳的不行,大家下的时候注意,别无必要的下载。
C#与C调用C++,非托管,含struct调用及enum公用,完整项目,可直接编译或运行。 项目将所有工程的输出统一到Debug。 vs2015+Framework4.6,注意工程的配置。 所有东西自写,只是出于样例参考的作用,所以代码规范...
.net反编译软件,可以反编译c#,vb,c++,dll 等 工程项目都可以编译,成功率一般在100%
完整的工程代码,在VS2015上编译通过,并且可以运行,实现MessagePack在C++和C#间传输数据
使用VS2013实现的代码,内容很简单,注意#using配置C#编译后类库的路径,并且C++编译后的文件夹中应拷入C#dll类库哦。
1.c++编译成dll。 2.c#调用非托管dll,演示中文字符串传递,以及回调的过程。 3.演示中文字符串传递,演示c#与c++的委托回调
在C#开发软件的过程中,要经常调用C/C++生成的dll,本文主要介绍用C/C++生成dll的步骤,以及用C/C++、C#两种语言实现dll的引用实现。本文使用的IDE是VS2019,文章通过具体实例进行讲解,大家可以跟着自己动手进行...
c# 调用c++ dll 调用opencv-wechat微信识别二维码。需要c++运行库。
最新的C++、C#源码查看工具,可以直接中exe、dll、obj中查看程序源代码
微软Visual Studio 2010 中C、C++、C#命令行编译器的使用
一个把dll反编译成C#,VB,C++源代码的利器。
工程包括:被注入的目标程序(C++ WinForm),注入dll, 注入程序(C++ WinForm),注入程序(C# WinForm),通过C++和C# 都可将dll注入目标程序中,目标程序可修改为其它程序,如微信。 在目录中含有已编译好的程序和dll,...
类型安全:C#是一种强类型语言,这意味着在编译时就能检测出许多类型相关的错误,从而提高了代码的安全性和稳定性。 垃圾回收:C#内置了垃圾回收机制,可以自动管理内存,减轻了程序员的负担,并减少了内存泄漏和...
反编译工具(C#, ( 反编译工具(C#,VB,DELPHI,C++,C).rar ) VB,DELPHI,C++,C).rar
自带的那个bat文件双击就能生成,若路径有问题,自行修改一下就可以,只需要保证文件夹存在
Reflector是一款比较强大的反编译工具,相信很多朋友都用过它,但reflector本身有很多局限性,比如只能一个一个的查看方法等,但幸好reflector支持插件功能目前网上有很多reflector的插件,本人找取了两个应用范围很广,...
一款比较强大的反编译工具,可用来查看DLL中的资源和代码文件