C ++应用程序是跨平台的吗?
我作为学生学到的第一件事就是C ++应用程序不能在不同的操作系统上运行。 最近,我读到基于Qt的C ++应用程序无处不在。 那么发生了什么? C ++应用程序是否跨平台?
-
源代码兼容。 如果我编译源代码,它会运行在任何地方。
-
API / ABI兼容性。 操作系统是否以代码能够理解的方式为其组件提供接口?
-
二进制兼容性。 代码是否可以在目标主机上运行?
源代码兼容
C++
是一个定义结构,内存,文件如何被读写的标准。
#include <iostream> int main( int argc, char ** argv ) { std::cout << "Hello World" << std::endl; }
写入stream程数据的代码(例如grep
, awk
, sed
)通常是跨平台的。
当你想与用户交互时,现代操作系统有一个GUI,它们不是跨平台的,并且导致代码被写入特定的平台。
像qt
或wxWidgets
这样的wxWidgets
可以实现多种平台,并且允许您为qt
而不是Windows
或iOS
进行编程,其结果与两者兼容。
这些匿名库的问题在于,为了平台间的一致性,他们将平台X的某些特定好处带走了。
这个例子可以在Windows
使用WaitForMultipleObjects
函数,它允许你等待不同types的事件发生,或者在UNIX上使用fork
函数,它允许你的进程的两个副本以显着的共享状态运行。 在用户界面中,表单的外观和行为略有不同(例如颜色select器,最大化,最小化,跟踪窗口外部鼠标的能力,手势行为)。
当你需要完成的工作对你来说很重要的时候,你最终可能希望编写特定于平台的代码来利用特定应用程序的优势。
C
库sqlite
是广泛的跨平台代码,但是它的低级IO是平台特定的,所以它可以保证数据库的完整性(数据真正写到磁盘上)。
所以像Qt这样的库可以工作,它们可能会产生不令人满意的结果,并且最终不得不编写本机代码。
API / ABI兼容性
不同版本的UNIX和Windows之间有某种forms的兼容性。 这些允许为一个版本的OS构build的二进制文件在其他版本的OS上运行。
在UNIX中,您的生成机器的select定义了兼容性。 您希望支持的最低操作系统版本应该是您的构build机器,并且它将生成与后续小版本兼容的二进制文件,直到它们进行重大更改(弃用一个库)。
在Windows和Mac OS X上,您可以select一个SDK,使您可以针对一组具有相同问题的操作系统进行中断更改。
在Linux上,每个内核版本都是ABI不兼容的,内核模块需要为每个内核版本重新编译。
二进制兼容性
这是CPU了解代码的能力。 这比你想像的更为复杂,因为x64芯片可以支持运行x86代码(取决于操作系统支持)。
通常情况下,一个C ++程序打包在一个容器(PE可执行文件,ELF格式)中,操作系统使用它来解压缩代码和数据部分,并加载库。 这使得最终的程序有二进制(代码types)和API(容器的格式)不兼容的forms。
此外,如果您编译x86 Windows应用程序(针对Visual Studio 2015上的Windows 7),那么如果处理器没有SSE2指令(大约10年前的CPU),代码可能无法执行。
最后,当苹果从PowerPC改为x86时,他们提供了一个仿真层,允许旧的PowerPC代码在x86平台上的仿真器上运行。
所以一般来说二进制不兼容是一个阴暗的地方。 可以生成一个识别无效指令的操作系统(例如SSE2),并在故障中模拟行为,这可以在出现新特性时进行更新,并保持代码的运行,即使它是二进制不兼容的。
即使您的平台无法运行某种forms的指令集,也可以进行仿真并performance出兼容性。
标准C ++是跨平台的,在“一次编写,任意编译”的意义上说,而不是在“编译一次,随处运行”的意义上。
这意味着如果你用标准的C ++编写程序,你可以在任何具有标准C ++实现的目标环境下编译并运行它。
但是,您可以在您的机器上编译您的程序,运送二进制文件,然后期望它在其他目标上运行。 (至less不是一般的,当然可以在特定条件下分发C ++代码中的二进制文件,但这些依赖于实际的目标,这是一个广泛的领域)。
当然,如果您使用额外的非标准function(如gcc的可变长度数组或第三方库),则只能在提供这些扩展和库的系统上进行编译。
一些类似Qt和Boost的库在许多系统上都可用(至less我相信这两个系统在Linux,Mac和Windows上),所以如果你使用这些系统,你的代码将保持跨平台。
您可以实现您的源代码在各种平台上编译 ,从相同的源代码向您提供各种二进制文件。
这不是像Java或C#那样“编译一次, 用适当的虚拟机在任何地方运行”,而是“一次写入, 用适当的环境 编译 ”,这是C一直在做的方式。
由于标准库不提供您可能需要的所有内容,因此您必须查找第三方库来提供该function。 某些框架 – 比如Boost,Qt,GTK +,wxWidgets等 – 都可以提供这个function。 由于这些框架是以在不同平台上编译的方式编写的,因此可以在前述意义上实现跨平台function。
如果你希望你的C ++代码是跨平台的,有很多东西需要注意。
显而易见的是对数据types进行假设的源代码。 你的long
可能在这里32位和64位。 数据typesalignment和结构填充可能不同。 有一些方法可以在这里“安全地玩”,比如size_t
/ size_type
/ uint16_t
typedefs等等,以及错误的方法,比如wchar_t
和std::wstring
。 需要纪律和一些经验来“正确”。
并非所有编译器都是平等的。 如果您需要在其他C ++编译器上编译源代码,则不能使用所有最新的C ++语言function,或者使用依赖于这些function的库。 先检查兼容性图表 。
另一件事是Endianess 。 举个例子,当你在一个平台(比如x86或者x86_64)上编写一个整数stream文件,然后在不同的平台(比如说POWER)上再次读取它时,你可能遇到问题。 你为什么要写整数文件? 那么,UTF-16 是整数…再次,纪律和一些经验,使这个相当无痛的很长的路要走。
一旦你检查了所有这些框,你需要确保你的代码库的可用性 。 尽pipestd::
是安全的(但是请参阅上面的“并非所有的编译器都是相同的”),像boost::
无辜的东西可能会成为一个问题,如果你超越了主stream。 (在过去的几年中,我帮助Boost人修复了一两个有关AIX / Visual Age的showstopper,仅仅是因为他们无法访问该平台来testing新版本…)
噢,注意那里的各种授权计划 。 一些改进跨平台function的框架(如Qt或Cygwin)都附有string。 这并不是说他们在正确的情况下帮助不大,只是需要了解版权/专有许可要求。
所有这一切,都有Wine (“Wine不是仿真”),它使得为Windows 编译的可执行文件可以在各种类Unix系统(Linux,OS X,* BSD,Solaris)上运行。 它的能力有一定的限制,但是它一直在变好。
是。 不,也许 什么是跨平台的C ++代码? 跨平台的C ++代码就是这样一个代码,可以在不同的操作系统下编译而不需要修改。
这意味着,如果您明确使用任何平台相关的标头,则您的代码不再是跨平台的。 Qt通过以下方式解决了这个问题:它为所有平台特定的东西提供了包装。 例如,假设您正在使用QFile
打开/读取/写入文件。 你的代码看起来像
QFile file(filename); file.open(QFile::ReadOnly); //other stuff
你可以在任何操作系统下编译这个代码,只要你有适合该操作系统的编译器和Qt库。 隐藏在QFile
下的代码将使用操作系统相应的文件处理函数,但是这不应该关注你。
另外,如果只使用标准库,则可以在任何存在C ++编译器的地方编译代码。
但是,已编译的应用程序并不是以Java应用程序的方式进行跨平台的 – 例如,您无法为Windows编译应用程序,然后在Linux中运行应用程序,则必须重新编译代码改为在Linux下。
C ++是一种编程语言。 文本。 因此,它不会在任何地方运行。
预计标准C ++代码在任何平台上的行为都是平等的; “跨平台”,如果你想。 写(严格)符合C ++代码需要pedantry,因为一些假设往往使依赖于实际实现的最终细节,这是从C + +目标inheritance的目标。
注意我们还在谈论C ++代码,而不是C ++程序。 事实上,当我们转向“程序”这个术语时,我们没有更多的保证,因为我们不再讨论C ++了。 而是编译器的输出。 这是可移植性开始消失的地方:可执行格式,ISA,ABI,低级例程等等。
你能依靠吗? 如果你不能,那么你需要通过重新编译它或使用特定于平台的元素来将你的C ++程序集成到它将运行的环境中。
C ++是跨平台的。 您可以使用它来构build可在多种不同操作系统上运行的应用程序。
什么是不跨平台的是将C ++转换成目标代码的编译器。 就我所知,没有一个单独的编译器具有所有必要的function,所以当你使用它编译C ++程序时,它将自动运行在Windows,Linux和Mac OS上。
Qt Creator与多个编译器集成,并构build自动化。 它可以很容易地在不同的设置和目标平台之间切换。 它为构build,运行和部署C ++应用程序提供支持,不仅适用于桌面环境,而且适用于移动设备。