C的哪些部分最便携?

Mig*_*uel 15 c lua portability c89

我最近阅读了Lua共同创作者Luiz H. de Figueredo和Roberto Ierusalimschy的采访,他们在那里讨论了Lua的设计和实现.至少可以说是非常有趣的.然而,讨论的一部分在我的脑海中带来了一些东西.Roberto称Lua是一个" 独立应用程序 "(也就是说,它是纯粹的ANSI C,它不使用操作系统.)他说,Lua的核心是完全可移植的,并且因为它的纯度已经能够移植很多更容易和甚至从未考虑过的平台(例如机器人和嵌入式设备).

现在这让我很奇怪.C一般来说是一种非常便携的语言.那么,C的哪些部分(即标准库中的部分)是最不可移植的?什么是可以预期在大多数平台上工作的?是否应该只使用一组有限的数据类型(例如避免short和可能float)?怎么样FILEstdio系统?mallocfree?似乎Lua避免了所有这些.这会把事情发挥到极致吗?或者它们是可移植性问题的根源?除此之外,还有什么其他方法可以使代码非常便携?

我问这一切的原因是因为我目前正在用纯C89编写一个应用程序,并且它最好是尽可能便携.我愿意采取一条中间路来实现它(足够便携,但没有那么多,我必须从头开始编写所有内容.)无论如何,我只想看看编写最好的C代码的关键.

最后,所有这些讨论仅与C89有关.

lhf*_*lhf 13

在Lua的情况下,我们没有太多抱怨C语言本身但我们发现C标准库包含许多看似无害且直接使用的功能,直到你认为他们不检查他们的有效性的输入(如果不方便则很好).C标准说处理错误的输入是未定义的行为,允许这些函数做任何他们想做的事情,甚至崩溃主机程序.例如,考虑一下strftime.有些libc只是忽略无效的格式说明符,但其他libc(例如,在Windows中)崩溃!现在,strftime不是一个至关重要的功能.为什么崩溃而不是做一些明智的事情?因此,在调用strftime之前,Lua必须对输入进行自己的验证,并将strftime导出到Lua程序变成一件苦差事.因此,我们试图通过针对核心的独立性来清除Lua核心中的这些问题.但Lua标准库不能这样做,因为他们的目标是将设施导出到Lua程序,包括C标准库中可用的内容.


rli*_*bby 9

"独立式"具有C的粗略的,独立式的主机不需要提供任何标准库的上下文中,特定的含义,包括库函数malloc/ free,printf等.某些标准头仍需要,但它们只定义类型和宏(例如stddef.h).


小智 6

C89允许两种类型的编译器:托管独立编译器.基本的区别是,托管的编译器提供了所有的C89库,而一个独立的编译器只需要提供<float.h>,<limits.h>,<stdarg.h>,和<stddef.h>.如果您将自己限制在这些标头中,您的代码将可移植到任何 C89编译器.

  • @larsmans:这几乎等同于说“代码可能有错误”。避免实现定义的行为并不难,尤其是当您针对 C 的独立子集时。 (2认同)

Fre*_*Foo 5

这是一个非常广泛的问题。我不打算给出肯定的答案,而是提出一些问题。

请注意,C 标准将某些内容指定为“实现定义”;符合标准的程序将始终在任何符合标准的平台上编译和运行,但它的行为可能因平台而异。具体来说,有

  • 字大小sizeof(long)在一个平台上可能是四个字节,在另一个平台上可能是八个字节。的尺寸shortintlong等各自具有某一最小(通常相对于彼此),但在其他没有保证。
  • 字节序int a = 0xff00; int b = ((char *)&a)[0];可以分配0b一个平台-1上,另一个平台上。
  • 字符编码\0始终为空字节,但其他字符的显示方式取决于操作系统和其他因素。
  • 文本模式 I/Oputchar('\n')可能在一个平台上产生一个换行符,在下一个平台上产生一个回车符,以及在另一个平台上的每一个的组合。
  • char 的签名。a 可能会也可能不会char采取负值。
  • 字节大小。虽然现在,一个字节几乎到处都是八位,但 C 甚至迎合了少数没有它的奇特平台。

不同的字长和字节序是常见的。在任何文本处理应用程序中都可能出现字符编码问题。具有 9 位字节的机器最有可能在博物馆中找到。这绝不是一个详尽的清单。

(请不要写 C89,这是一个过时的标准。C99 添加了一些非常有用的可移植性内容,例如固定宽度的整数int32_t等。)