为什么编写可移植的C程序很困难?

我想知道,为什么在没有包含胶水代码的情况下让程序在许多操作系统(如Windows和Linux)中运行太难了。 它们都共享相同的架构(x86),所以我认为它应该很简单。 此外,C是标准化的,那么为什么这些操作系统的实现不同? 为什么很难遵循标准并为所有操作系统实现通用库?

我用C编程了将近两年,目前我使用glib来实现可移植性。

我不是在寻找这个问题的解决方案,我已经为此目的使用了glib。 但是我想知道为什么有必要,为什么在没有差异的情况下制作一个C库是很困难的。

[加]

例如,当我用C / Glib编写程序时,我使用gchar / gint等类型确实是C基元类型,在wikipedia中关于glib,它说:

“特征

在基本级别上,GLib提供了类型定义,替换了C基本类型char,int,float等,以便提高可移植性“

为什么C原始类型不可移植和整个语言?

感谢所有的答案。

使您的基本C程序计算一点并打印结果工作很容易。

问题在于任何实质性的C程序都将依赖于操作系统中的大量服务,而这些服务在很多方面存在差异。 文件I / O往往类似,但是当涉及到图形时,它们差别很大。 这就是问题的症结所在。

为什么C原始类型不可移植和整个语言?

在创建C时,最重要的是int使用目标机器的自然字大小(或半字大小)(当时在PDP-10上可能是18或36位!)重要的是int的位数很容易预测,更不用说在所有硬件上都是一样的。 效率是最重要的考虑因素,特别重要的是程序没有太多的指令,因此它可以被包装到当天的小记忆中。 例如,没有人会想要在16位机器上模拟32位算术 – 这可能使执行算术所需的指令数量增加三倍,从而无法将更大的程序放入内存中。

为什么实施通用库很难?

这根本不难。 问题不在于没有通用的图书馆; 问题是人们不能就什么构成通用图书馆达成一致。 (参见:GTK,KDE,QT,AT&T U / WIN + AST,等等令人作呕。)但实现一个好的真的很难。 至于为什么这很困难:图书馆设计只​​是一个难题,合理的人可以而且对于什么是好的设计不一致。 因此,多个设计激增,可移植性由董事会完成。

C语言中非常薄的标准库加剧了这种情况。但是,我们不要忘记,程序员很幸运能够获得64KB的代码和另外64KB的数据库。 到C ++出现的时候,他们可以像标准模板库那样标准化一个巨大的臃肿的猪。 但是当设计C库时,事情必须很小。 现在,当标准C库不适合当今更加雄心勃勃的应用程序时,所有C程序员都不同意单一标准。


戳一个教授,开个讲座……

如果你坚持核心标准并不难(K&R中的例子通常会以最小的修正运行)。 但核心标准并不支持人们想要做的许多事情。 小事如:

  • 在文件系统中生根
  • 比普通流式文本更复杂的IO
  • 要求操作系统访问时钟,打印机和网络
  • 与其他流程交谈

关于基元类型的可移植性:标准规定了这些类型的最小大小限制,但没有指定实际大小。 大多数平台支持的尺寸大于最小尺寸,但并非所有平台都具有相同的更大尺寸。 所以glib和其他跨平台项目定义了他们自己的类型,因此他们只需要#ifdef开关来获得正确的大小。

您的C程序与之交互的任何内容都将成为依赖项。 如果这些依赖关系在所有系统上的每个C实现中完全相同 ,那么你很幸运,你的程序是可移植的。

基本文件I / O操作就是这种方式。

但是,如果在系统上实现代码的方式存在一个差异,那么它就不再可以移植到该系统。

因此,如果您的代码没有触及任何内容,那么它就是可移植的。

我认为这里的主要思想是最大限度地提高可移植性,这样您就可以最大限度地减少必须更改的内容以便移植到新系统。

代码是可移植的,但这不是问题。

问题是大多数大型应用程序使用属于操作系统的库。 因此,例如,如果您编写网络应用程序,它可能会使用Windows内置的UPNP库,OS X上的Bonjour库以及其他unix版本的其他零配置服务。

另一个例子是一个简单的记事本应用程序。 它可能会使用运行它的操作系统的本机保存文件对话框。 需要为每个OS编译不同的版本以绑定到该OS的保存文件对话库。

我希望这些例子足够清楚:)

对于java / ruby​​ / …有人移植了VM,你的代码就运行了。 只要您对VM提供的服务没有问题,这就变得简单了。 在C中,您必须为自己完成所有工作,因为您可以直接与硬件和操作系统进行交互。 这增加了依赖性,但为您提供了强大的function和灵活性。 这就是让C很棒的原因,但是如果你切换操作系统或硬件,这可能会很痛苦。

显然,某些软件需要特定于操作系统的function,但考虑在C中创建的内容而不使用这些内容非常有趣:

  • AC或C ++编译器(虽然不是所有的标准库)
  • 任何汇编语言的汇编程序
  • 上面的链接器
  • 脚本语言的解释器
  • 文本处理工具,如sed,grep等。
  • 一个简单的编辑器(有人记得编辑?)

事实上,所有基本开发工具都可以在C中开发(并且历史上已经开发),而不使用特定于操作系统的function。

为什么C原始类型不可移植和整个语言?

基本类型是可移植的,因为它们保证支持最小范围的值(例如,int类型必须至少支持-32767到32767范围内的值)。 它们不能保证具有相同的大小或对齐限制,因为不同的体系结构具有不同的要求。

C标准试图在可移植性,性能和易于实现之间取得合理的平衡,这意味着在所有这三个方面都存在妥协。 编写有用且简单易用的C程序是可能的,但这意味着将自己局限于命令行驱动的接口,简单的文件I / O,并且不对字大小或对齐做出任何假设。

请记住,C是70年代早期的产物,当时占主导地位的计算环境包括通过基于哑巴字符的终端访问的大型时间共享系统; 处理器时间和内存都很昂贵,而且数据中心很少一次支持多个或两个不同的平台,因此性能比逐字节可移植性更受关注。 四十年后,情况不再如此,但也有四十年的遗留代码需要支持,因此语言定义不能过于彻底地改变。

我认为这是因为每个编译器在标准和便携之间以及在另一方面使用最佳的OS专有function之间存在紧张关系。

我认为ANSI C代码非常便携,只要你写入标准。 您的代码可移植到GNU和Microsoft都遵守标准的程度。

与其他更高级别的语言相比,C确实提供更多function。

不同的处理器(基于CISC和RISC),32位和64位确实以不同的顺序放置数据的比特流。 有一些支持API可以进行转换,但对于所有情况都不完全可靠。

Windows和Unix具有需要用于构建的自定义标志。