【问题标题】:Can header exist without being a file?标题可以存在而不是文件吗?
【发布时间】:2016-03-14 14:33:26
【问题描述】:

C: The Complete Reference 中,Herbert Schildt 这么说

标头通常是文件,但不一定是文件。编译器可以在内部预定义标头的内容。然而,出于所有实际目的,标准 c 头文件包含在与其名称相对应的文件中。

标题如何存在而不是文件? 这段话的主题是什么? 因为 .h 文件扩展名与标头一起使用。

【问题讨论】:

  • 例如,您可能会说#include "/path/to/some/named/pipe"。当然,您会期望命名管道始终存在于每个编译单元,但确保这可能比它的价值更困难(请记住,第一个“抓取”命名管道的编译单元可能会关闭该管道以供以后的编译单元使用)
  • 你能在引号周围添加更多上下文吗?
  • @inetknght 是正确的:“标头是一个标准标识符,可以映射到文件名,但不需要。[...] 然而,实际上, C 头文件几乎总是文件。” (我的 emph。)(人们可能仍然想知道为什么“几乎总是”:P)
  • 与这个问题并不真正相关,但很多人似乎不喜欢那本书。 stackoverflow.com/a/579795/646887
  • @KlasLindbäck:Peter Seebach 的C: The Complete Nonsense 是一个相当长的批判性评价。是的,他在 Schildt 对头文件的描述中提到了一部分,“他因‘通常’而受到赞誉。不幸的是,其余的都不是很好。”

标签: c header-files


【解决方案1】:

C 标准确实对 #include 预处理指令引用的头文件和源文件有所不同:

6.10.2 源文件包含

约束

1 #include 指令应标识可由实现处理的头文件或源文件。

语义

2 形式的预处理指令

# include <h-char-sequence> new-line

在实现定义的位置序列中搜索由 分隔符之间的指定序列唯一标识的标头,并用标头的全部内容替换该指令。如何指定位置或标识的标头是实现定义的。

3 形式的预处理指令

# include "q-char-sequence" new-line

导致将该指令替换为由 " 分隔符之间的指定序列标识的源文件的全部内容。以实现定义的方式搜索命名的源文件。如果不支持此搜索,或者如果搜索失败,指令被重新处理,就像它读取一样

# include <h-char-sequence> new-line

具有与原始指令相同的包含序列(包括 > 字符,如果有的话)。

编译器可能会实施一种方案,其中标准头文件实际上并不作为文件存储在文件系统中。但是指令#include "filename.h"被指定为首先以系统特定的方式搜索文件,然后搜索标准头文件,就好像该指令是#include &lt;filename.h&gt;

请注意,文件扩展名.c.h 纯粹是为了区分包含声明的文件和包含实际代码和数据定义的文件的约定。除了用于标准标题的名称外,标准中没有任何内容要求此约定。有些人根据特定需求使用具有不同扩展名或根本没有扩展名的其他约定,但绝大多数 C 程序员会认为这是不好的做法。

Shafik Yaghmour 在回答类似问题时引用了 C99 的基本原理,该问题明确了委员会对此事的意图:https://stackoverflow.com/a/27262904/4593267

【讨论】:

    【解决方案2】:

    C 标准明确表示标头是文件,所以我认为不是。

    6.10.2 源文件包含

    #include 指令应标识可以 由实现处理。

    但是,对于给定系统而言,什么是文件是实现定义的。理论上它可能是一个硬件端口、管道或其他一些愚蠢的东西。大多数主要操作系统都有可能将端口或管道视为文件(例如在 Windows 中,文件和硬件端口以相同的功能打开。)

    【讨论】:

    • 在第 7.1.2 节“标准标题”中,标准有一个脚注A header is not necessarily a source file, nor are the &lt; and &gt; delimited sequences in header names necessarily valid source file names.,因此该文件仅指“源文件”,而不是标题
    • @zauguin 是吗?脚注在 ISO 标准中并不规范。
    • @Lundin:确实!可以改进标准的语言以消除这种歧义。我仍然认为委员会暗示编译器中嵌入了头文件,而不是系统特定的伪文件。
    • 无论如何,我认为在 90 年代中期发生了一场大运动,语言委员会吸了很多非法物质,然后就未来的计算机进行了头脑风暴,它们不会有文件或文件扩展名。在那次运动中的某个地方,所有包含的 C++ 标准库都删除了 .h 扩展名,这是一个打破所有现有 C++ 代码的绝妙举动。我可以看到志同道合的人会想出标题或文件的想法。它可能是独角兽,也可能是彩虹。
    【解决方案3】:

    假设的 C 编译器不需要文件系统。否则它可以处理#include 指令:

    • 它可以查询数据库(IIRC 一些 IBM 编译器在 1980 年代这样做,数据库包含 AST 的缓存)

    • 它可以处理标准包含,否则,即当它遇到#include &lt;stdio.h&gt; - 在某些条件下 - 更改其内部状态(根据标准要求)而不访问任何标题 文件。换句话说,标准头文件可以是“内置的”。

    实际上,我今天所知道的所有 C 编译器都使用文件系统作为头文件。但是请阅读precompiled headers in GCC

    顺便说一句,C11 规范n1570 中提到的“头文件”不需要文件系统(与通常的操作系统一样)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-09
      • 2019-08-20
      • 2015-09-23
      • 2015-08-11
      • 2015-07-15
      • 2011-01-28
      • 1970-01-01
      • 2020-05-21
      相关资源
      最近更新 更多