C 标准库中的头文件可以包含另一个头文件吗?

时间:2021-01-24 09:05:41

标签: c include language-lawyer c-standard-library

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

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

3 个答案:

答案 0 :(得分:2)

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

<块引用>

7.1.2 标准标题(强调我的)

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

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

<块引用>

4.一致性

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

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

答案 1 :(得分:2)

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

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

某些系统标头被明确指定为包括其他标头:

<块引用>

7.25 类型泛型数学<tgmath.h>

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

<块引用>

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

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

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

答案 2 :(得分:2)

<块引用>

我依稀记得“没有C标准库的头文件 应包括 C 标准库的任何其他头文件,除非 特别允许”。

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

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

然而,正如@chqrlie 在 their answer 中指出的那样,标准明确指定某些标准库头文件包含特定的其他标准库头文件。

<块引用>

但奇怪的是,我找不到这样的规则 写在 C11 中。我会在 7.1.2“标准 标题”。

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

<块引用>
Is there such a rule in C?

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

<块引用>
Is there such a rule in POSIX?

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

<块引用>
Is there such a rule in any other standard?

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

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

<块引用>

标准标题可以以任何顺序包含;每个都可以包括在内 在给定的范围内不止一次,效果与被 只包含一次,除了 [关于 assert.h 的警告; ...]。但是,如果一个标识符被声明或定义在多个 一个标头,第二个和后续相关联的标头可能是 包含在对标识符的初始引用之后。

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