ISO C 标准定义了两个符合实现的类别。

7
我阅读了关于GCC的官方手册(该链接仅供参考),其中第二章1节有一个问题需要翻译,但是我对文本内容进行了翻译。该篇文章讲述了ISO C标准的两种实现:完整实现(称为符合主机环境的实现)和轻量级实现(称为符合独立环境的实现)。在每个标准实现中都存在两种环境:运行在完整实现中的主机环境和运行在轻量级实现中的独立环境。独立环境仅为操作系统内核提供库设施,而主机环境则提供所有的库设施,并通过int main(void)int main(int, char *[])函数启动。此外,自C99以来,轻量级实现只需提供<float.h><limits.h><stdarg.h><stddef.h>库设施,自AMD1以来也需要提供<iso646.h>库设施。自C11以来,还需要提供<stdbool.h><stdint.h><stdalign.h>库设施。对于轻量级实现,不需要提供在C99中添加的复杂类型。因此,操作系统内核通常处于轻型环境中,而使用操作系统设施的程序则处于主机环境中。
3个回答

12

这是两者兼备。

标准定义了两种运行时环境。 一种具有所有语言功能,以及标准运行时库的微小子集和其他实现定义的内容。 这是一个“自由环境”,(如您所猜测的)旨在用于裸机编程,例如操作系统内核。

另一种更复杂的环境包括上述所有设施以及标准运行时库的所有内容。 那就是“宿主环境”,旨在用于应用程序编程。

现在,实现只需要包含自由环境的设施。 如果只有这些,则称为“自由实现”。 用于深度嵌入式微控制器的交叉编译器通常是自由实现,因为标准C运行时的许多部分都没有意义或太大而无法安装。

实现宿主环境是可选的; 如果实现提供宿主环境,则称之为“主机实现”。 主机实现还必须提供自由环境,即仅提供自由实现设施的编译模式。 (此模式通常用于编译类似C运行时本身的东西,其中大部分只是更多的C。)

最后,main的标准签名(int main(void)int main(int,char **))是“宿主”环境的一部分。 自由环境也可以使用这些签名,但也可以定义main的签名为它喜欢的任何东西(void main(void)很常见),或者使用入口点的不同名称。


5
C11 4/6:
两种符合规范的实现形式是托管和独立。符合规范的托管实现应接受任何严格符合规范的程序。符合规范的独立实现应接受任何严格符合规范的程序,其中库条款(第7条)中指定的特性的使用仅限于标准头文件 <float.h>, <iso646.h>, <limits.h>, <stdalign.h>, <stdarg.h>, <stdbool.h>, <stddef.h>, <stdint.h> 和<stdnoreturn.h> 的内容。
首先请注意,“实现”在C标准的上下文中意味着“C编译器的实现”,而不是其他任何东西。
正如您在问题中正确陈述的那样,独立实现是针对没有操作系统的系统的编译器。换句话说,独立实现编译器会生成运行在“裸机”CPU上的嵌入式应用程序或作为操作系统本身的程序。而托管实现是针对在操作系统之上运行的应用程序的编译器。
用于独立应用程序的编译器只需要提供上述提到的头文件。其余的头文件(例如stdio.h)在标准的“第7条”中定义,但对于独立实现来说并不是必需的。
请注意,许多库对于托管和独立实现都不是强制性的,例如复数库: C11 7.3.1:
“定义宏__STDC_NO_COMPLEX__的实现不需要提供此头文件或支持其任何功能。”
此外,两种不同的执行环境,独立和托管,允许不同的main()语法,更多信息可以在此处找到。程序员之间非常普遍的一个误解是,在C中唯一允许的形式是int main(),这只有在托管环境下才是真的。
例如,独立程序可以从重置中断服务例程开始。从那里,它可以调用一个void main()函数,或者完全调用其他函数:这是实现定义的。

谢谢。这对我来说非常有用和有趣。 - Andrey Bushman

1
这意味着在启动时不需要独立的环境来执行您的main()函数。例如,它可能正在寻找_main()(确切的名称和签名是实现定义的)。

如果我使用独立环境,那么我可以为入口点设置其他名称吗? - Andrey Bushman
你可能不能设置它,但是实现独立环境的人可以。 - zwol
@Bush 你需要查阅相关文档,了解入口点应该如何提供。 - Nikos C.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接