21

我的问题主要与第四节第六段有关。

两种形式的一致性实现是托管的和独立的。符合要求的托管实现应接受任何严格符合要求的程序。

据我了解,这构成了典型的应用程序环境,具有文件系统、分配的内存和线程......

符合标准的独立实现应接受任何严格符合标准的程序,其中库条款(第 7 条)中指定的功能的使用仅限于标准头文件<float.h><iso646.h><limits.h><stdalign.h><stdarg.h><stdbool.h><stddef.h><stdint.h>和的内容<stdnoreturn.h>

...这构成了典型的内核和/或嵌入式、最小的环境,没有标准文件系统、分配的内存或线程(除其他外)。

一个符合要求的实现可能有扩展(包括额外的库函数),只要它们不改变任何严格符合的程序的行为。

似乎这使托管实现可以自由地将自己称为托管或独立实现,并且当涉及到文件系统、分配的内存或线程(以及其他事物)时,这些可以属于扩展类别,因此它只能实现一个接口,每次都返回一个指示错误的值。仅举几个:

  • fopenfgets并且malloc可以返回NULL
  • fprintf, fscanf,fputc并且fgetc可以返回EOF
  • thrd_create可以返回thrd_error(表示“请求无法被兑现”)

这意味着第四节、第六节给出的区别实际上是没有意义的。是否有任何要求可以保证这些功能在托管和独立实现中的某些实际功能级别?例如,是否要求上面的那些函数实际上能够返回它们相应的失败值以外的东西?

4

4 回答 4

22

引用的段落已经很好地说明了这一点。

托管执行环境也是独立的,但反之则不然。编译器只需要提供一个独立的实现。例如,gcc 严格来说只是独立的,因为不包括标准库。但是,它假定它在为托管环境编译时可用(默认),假设 lib 在系统上可用(如 glibc)。看这里

简单地说,独立只是语言。它不需要支持任何库,只需要一些头文件(主要用于常见类型和实现特定的东西,如数值限制等)。这意味着标准库不需要存在 - 相应的头文件也不存在。Reason 是一个独立的环境,很可能没有文件、显示等设施。它用于内核、裸机嵌入式等。

请注意,例如 gcc 将在为托管环境-fhosted(对于独立式,它实际上没有,因此您可以使用strcmp具有完全不同语义的函数。但是,它假定存在 mem...-functions,因为它们用于普通代码,例如结构分配。

因此,如果为裸机构建,您应该始终通过-ffreestanding.

如果托管实现称自己为freestanding,那么它显然不再是托管实现。但是,一旦它自称为托管,它就必须提供标准所需的所有设施,并且不允许只实现虚拟对象,而必须提供标准中定义的语义。

只是说清楚:引用的部分允许一个独立的环境省略库的所有功能,除了少数列出的标题。因此,您可以自由地提供任何其他库并使用相同的名称,但可以做任何您喜欢的事情。由于那不是标准库,因此不需要合规性。

5.1.2.1进一步声明“任何可用于独立程序的库设施,除了第 4 条要求的最小集合之外,都是实现定义的。”。这确实支持我的说法。旁注:它也不需要main()作为程序入口点。

于 2015-06-14T01:47:20.020 回答
2

标准定义的托管各自独立的实现是最小定义。这两种变体都是可以在广泛的实际系统上合理实施的最小公分母。

定义这种最小的、可行的集合的基本原理是指定针对两种风格中的任何一种的程序必须如何看待,以便在理想情况下在符合各自风格的所有实现上编译和运行预期结果。

严格符合(即,一)标准的程序具有最大的可移植性。

不用说,实际存在的实现,无论是独立的还是托管的,通常都提供了大量的扩展,就标准而言这很好——有一个警告是扩展不能使严格符合的程序无效。

回到你的问题:标准所做的区别——理论——很清楚。实际上,现有的实现——实践——在标准的最低要求之间和之外的范围很广,但受制于严格遵守程序的“不得改变行为”条款(针对托管或独立实现,不依赖任何扩展)。

顺便说一句,您关于标准库虚拟函数的示例是正确的:对于独立实现,这些只是允许扩展的一个有趣案例:没有严格符合针对独立环境的程序无论如何都会调用它们。作为托管环境的一部分,它们会合规但无用。(当某些系统资源耗尽时,实际上可能会遇到这种情况,或者它们可能是测试存根实现。)

于 2019-12-08T11:48:55.933 回答
1

有很多种 C 实现,针对多种不同的执行平台,其中许多可以提供各种有用的功能并保证其他人不能。该标准的作者决定,在大多数情况下,针对各种平台和应用领域的实现应该提供哪些类型的特性和保证,以及应该如何提供它们应该足够明显,因此不需要制定标准关注这些细节。另一方面,需要文件 I/O 之类的应用程序的数量以及可以提供它们的平台数量足以证明将包含此类功能的那些实现识别为“特殊”是合理的。

通常,旨在为独立使用而设计的实现可以在无法有效处理托管实现的平台上使用。尽管该标准对一些较小的 C 平台提出了一些超出实际要求的要求,但在只有足够存储空间来容纳 256 条指令和 16 字节的变量的处理器上,一些几乎符合要求的 C 实现可以非常有用。如果像数字厨房温度计/定时器这样的小工具没有文件系统或控制台,为什么要浪费存储在标准输出描述符之类的东西上呢?

此外,由于该标准没有定义独立应用程序可以执行 I/O 的标准方法,并且由于不同平台处理 I/O 的方式不同,因此几乎独立应用程序将针对特定目标平台或平台范围。不公开自然特性或保证底层平台将提供的托管实现对于运行不需要此类特性或保证的程序可能很有用。然而,如果不使用特定于平台的特性和保证,嵌入式程序不可能做很多事情,因此不允许程序员访问这些事情的独立实现将无法做很多事情。高质量的实现应该允许程序员使用任何可以帮助他们完成他们需要做的事情的特性或保证,尽管有些可能需要使用编译选项来确保他们不会做任何古怪的事情。出于某种原因,认为标准委员会的决定可能已经成为一种时尚。某些实现和应用领域,其中特性或保证的价值不能证明成本合理,这表明程序员不应期望实现提供对低级编程有用且平台将提供的特性或保证基本上是零成本。

于 2017-04-04T22:29:19.020 回答
0

有一些独立的环境不能成为托管环境。阻止独立环境成为托管环境的两个已知条件是:

sizeof(char) == sizeof(int);
sizeof(size_t) < sizeof(int signed);
// SIZE_MAX < INT_MAX

托管环境明确要求

sizeof(char) < sizeof(int);
// (int)EOF != (char)EOF;
sizeof(int unsigned) <= sizeof(size_t);
// UINT_MAX <= SIZE_MAX

如果sizeof(char) == sizeof(int),EOF未定义。

如果argc > SIZE_MAX,你不能打电话main

于 2020-12-10T18:12:05.600 回答