3

我依稀记得一条规则,“C 标准库的头文件不得包含 C 标准库的任何其他头文件,除非特别允许”。但奇怪的是,我在 C11 中找不到这样的规则。我本来希望它出现在 7.1.2“标准标题”中。

  • C中有这样的规则吗?
  • POSIX中有这样的规则吗?
  • 在任何其他标准中是否有这样的规则?
4

3 回答 3

3

搜索从 Ansi-C (C90) 到最新草案的 C 标准,并进一步浏览历史参考资料,如 Unix V7 手册和 K&R 书籍,我找不到该规则的参考资料。

标准头文件的内容、位置和实现是特定于实现的,一些类型和宏定义在多个头文件中,因此需要一致的方案来避免重新定义警告,并且在常见的 C 库实现中通过条件包含来实现。

某些系统标头被特别指定为包括其他标头:

7.25 泛型数学<tgmath.h>

标头<tgmath.h>包括标头<math.h><complex.h>定义了几个类型通用的宏。

7.26 线程<threads.h>
7.26.1 简介
头文件<threads.h>包括头文件<time.h>、定义宏、声明类型、枚举常量和支持多线程执行的函数。

一些标准 POSIX 头文件也被记录为包括其他系统头文件。

除非程序员正在实现 C 库,否则该规则无论如何都没有区别:记录为定义标准类型、枚举常量、宏、函数或变量的系统头文件应在使用此标识符之前包含。系统标头可以按任何顺序包含,多次包含不应该导致任何问题。

于 2021-01-24T13:52:58.833 回答
2

据我所知,它没有明确说明允许(或不允许)。但我相信以下段落暗示了这种可能性

7.1.2 标准标题(强调我的)

4如果使用,标题应包含在任何外部声明或定义之外,并且应首先包含在第一次引用它声明的任何函数或对象之前,或者它定义的任何类型或宏。

当我们在一致性部分交叉引用这个“应该”要求时

4. 一致性

2如果违反了出现在约束或运行时约束之外的“应”或“不应”要求,则行为未定义。未定义的行为在本国际标准中以“未定义的行为”一词或省略任何明确的行为定义来表示。这三者在重点上没有区别;它们都描述了“未定义的行为”。

因此,如果要在不包含 的情况下调用该abs函数stdlib.h,则行为将是未定义的。本质上未定义的行为包括事物“工作”的可能性。因此,如果另一个标准标头包含stdlib.h并且程序“有效”,则这与上述合同一致。

于 2021-01-24T09:35:08.423 回答
2

我依稀记得一条规则,“C 标准库的头文件不得包含 C 标准库的任何其他头文件,除非特别允许”。

C 语言规范或 POSIX 标准中没有这样的规则。这两者,尤其是第一个,都避免指定诸如此类的实现细节。它们描述了用户可以依赖的积极结构和语义,但通常不限制实现以避免特定的结构或细节。

在大多数情况下,标准也没有指定任何特定的标头确实包含其他标头,因此,就样式和可移植性而言,编写代码就像没有标准标头包含任何其他标头一样是明智的。更一般地说,这导致了一个共同的风格指导,即您编写的每个源文件,包括头文件,都应该针对使用的每个标识符,或者适当地声明该标识符本身,或者#include记录一个头文件来声明它。

但是,正如@chqrlie 在他们的回答中指出的那样,该标准明确指定某些标准库头文件包含特定的其他标准库头文件。

但奇怪的是,我在 C11 中找不到这样的规则。我本来希望它出现在 7.1.2“标准标题”中。

这确实是人们在 C11 中看到的地方。正如您所说,它没有表达任何具有您描述的效果的规则。

Is there such a rule in C?

不,这将与上述其他规定不一致。此外,在一些假定符合 C 实现中,标准头文件比@chqrlie 指出的其他 #include标准库头文件更多。

Is there such a rule in POSIX?

不,这将与上述其他规定不一致。此外,在一些假定符合 POSIX 的 C 实现中,标准头文件比@chqrlie 指出的其他 #include标准库头文件更多。

Is there such a rule in any other standard?

我不知道与 C 标准库相关的任何其他标准。代码约定种类繁多,可以想象一个或多个关于编写程序和库头的规则,但标准库不在此类约定的范围内。然而,显然,没有人可以权威地谈论所有标准的世界。

提出 C11 的第 7.1.2/4 段也许也是相关的,其中部分内容是:

标准标题可以以任何顺序包含;每个都可以在给定范围内多次包含,与仅包含一次没有任何不同,除了 [关于 assert.h 的警告;...]。然而,如果一个标识符被声明或定义在一个以上的头文件中,则第二个和随后的相关头文件可能包含在对该标识符的初始引用之后。

C 语言规范明确拒绝将标准库头文件实现为用 C 语言表示的普通源文件的任何要求,但请注意,在特定实现提供这种表示的范围内,这明确提出了某些标识符可能由多个头文件声明或定义。尽管不能保证会发生,并且可能会出现其他方式,但它与某些标头(包括其他标头)是一致的。

于 2021-01-24T14:49:55.087 回答