编程语言的可移植性意味着,用一种编程语言在一个系统上编写的程序经过很少改动或者不经修改就可以在其他系统平台上运行。
要想了解可移植性必须要知道:1.什么是程序?2.什么是系统平台?
什么是程序
首先,我们得知道程序的本质是什么?程序的本质就是一连串能被CPU识别并执行的有0、1代码组成的指令即目标代码(0、1组成的代码)。不同类型的CPU指令集是不同的,相同的一段0、1代码intelCPU能识别,ARM CPU就不能识别产生错误。
其次,我们得知道程序的运行原理是什么?大家都知道程序是运行在操作系统之上的,而大家不知道的是:程序要想在操作系统上运行就需要在程序的头部嵌入一段启动代码,此代码相当于程序和操作系统之间的接口,它包含操作系统所需要的加载和重定位信息。如果没有这段启动代码程序很难在windows,linux等操作系统上作为一个普通应用程序运行。到这里我们可以清楚的知道:程序=目标代码+启动代码,两者缺一不可,只有这样程序才能在系统上运行起来。
不同的操作系统,它们的启动代码接口是不同的,例如在Intel CPU上运行的xp和linux的启动代码接口是不同的,所以同一种程序它们的启动代码是不同的。但是因为都是INtel CPU,所以程序的目标代码(0、1代码)是相同的。
什么是程序呢,程序=目标代码+启动代码
什么是系统平台
这里的系统平台是指cpu+操作系统的组合:如intel CPU+windows xp、intel CPU+Mac Os X、intelCPU+linux这是三个不同的系统平台,ARM cpu+linux与intel Cpu+linux也是不同的系统平台。
为什么系统平台是CPU+操作系统的组合呢,我们从上面了解到程序=目标代码+启动代码。目标代码随着CPU类型的不同而不同,启动代码随着操作系统的不同而不同,因此系统平台是CPU+操作系统。
可移植性的本质
那么目标代码和启动代码是怎么生成的呢?答案是编译器。编程语言编写的程序首先要被编译器编译成目标代码(0、1代码),然后在目标代码的前面插入启动代码,最终生成了一个完整的程序。所以编程语言的可移植性依赖于它们的编译器是否强大,是否在多个平台上都有这种编程语言的编译器。例如C编译器在大约40种系统上可用,包括从8位微处理器的计算机到Cray超级计算机。
要注意的是,程序中为访问特定设备(如显示器)或者操作系统(如windows xp 的API)的特殊功能而专门编写的部分通常是不能移植的。
综上所述,一个编程语言的可移植性强不强取决于1.不同平台编译器的数量 2.对特殊硬件或操作系统的依赖性
移植是基于操作系统的。但是这个时候,我们需要注意一点:基于各种操作系统平台不同,应用程序在二级制级别是不能直接移植的。我们只能在代码层去思考可移植问题,在API层面上由于各个操作系统的命名规范、系统调用等自身原因,在API层面上实现可移植也是不大可能的。那怎么才能实现可移植呢? 我们首先来看看现在主流的Windows和Linux平台下代码可移植性。有什么办法解决这个问题呢?答案是:在各个平台之间,基于大部分需求抽象出一个中间层。在中间层中,中间层用了屏蔽底层细节,在我们程序员看来C言语库就是这样一个中间层的作用。在各个平台下,我们默认C标准库中的函数都是一样的,这样基本可以实现可移植。但是对于C库本身而言,在各种操作系统平台下其内部实现是完全不同的,也就是说C库封装了操作系统API在其内部的实现细节。 因此,C语言提供了我们在代码级的可移植性,即这种可移植是通过C语言这个中间层来完成的。 当然,大家都可以看出上面的可移植是有条件的,C语言本身不能实现完全的可移植,为什么呢?因为,在我们程序中,我们经常会调用系统API,由于这些API在C语言中没有对其封装,所以我们只能用使用其原始的API,对于原始的API在各个操作系统中他们命名不同,就不能跨平台移植。所以,我们要写出完完全全的跨平台的程序,还是需要其他的一些手段。例如在我们的代码中下功夫。以下代码可以帮助我们实现各平台之间的可移植:#ifdef _WINDOWS_
CreateThread(); //windows下线程的创建
#else
Pthread_create(); //Linux下线程的创建
#endif
对于头文件,也使用同样的预编译宏来实现。如:
#ifndef _WINDOWS_
#include <>
#else
#include <>
#endif
这样就可以实现代码的可移植了。在编译的时候只要通过#define就可以选择在那个平台下完成程序的编译。
综上所述,我们都是将C,C++等各种语言当作中间层,以实现其一定程度上的可移植。如今,语言的跨平台的程序都是以这样的方式实现的。但是在不同的平台下,仍需要重新编译。