“外部声明或定义”不代表我的想法吗?

时间:2013-05-12 10:02:12

标签: c++ header-files language-lawyer

17.6.2.2标题[using.headers]

  

3)翻译单元应仅包括任何标题之外的标题   外部声明或定义,并应包括标题   在该翻译单元中第一次引用之前的词汇   在该标题中声明的实体。

如果我的解释是正确的:

extern "C"
{
   #include "smth.h"
}

是非法的(那里有很多)。

我是否想要诠释? “外部声明”和“外部定义”是否意味着其他内容(在此上下文中)?

2 个答案:

答案 0 :(得分:4)

标头在标准中定义为声明或定义C ++标准库的元素。这不包括用户的.h文件。见§17.6.1.2:

  

标题中声明或定义(视情况而定)C ++标准库的每个元素。

     

C ++标准库提供了52个 C ++库头,如表14所示。

     

C标准库的功能在26个附加标题中提供,如表15所示。

所以你给出的例子很好(只要.h文件本身不包含一些标准库头)。但是,这不会是:

extern "C"
{
   #include <string>
}

要进一步备份标头和源文件(包括.h文件)之间的分离,#include预处理指令定义为包含带有<h-char-sequence>语法的“标题”,并且包含"q-char-sequence"语法的“源文件”(第16.2节)。所以你的#include "smth.h"包含了一个源文件,而不是一个标题。源文件被定义为程序的文本,它与它包含的标题一起组成一个翻译单元:

  

该程序的文本保存在本国际标准中称为源文件的单元中。通过预处理指令#include将源文件与所有头(17.6.1.2)和包含的源文件(16.2)一起,减少任何条件包含(16.1)预处理指令跳过的任何源行,称为翻译单位。

我认为这种措辞的目的是将标准库标题与其表示分离。他们没有理由将它们存储为C ++源文件,即使它们通常也是如此。包含特定标题只需要使程序可以使用适当的声明。

答案 1 :(得分:1)

我认为Joseph Mansfield's answer大多正确地解释了“header”这个词(它仅指§17.6.1.2[headers]中定义的标准库头部),除了我认为它还包括在附录D,如脚注176(在N3936中)将<iso646.h><ciso646>都称为“标准标题”。这个答案侧重于短语外部声明或定义的含义。

似乎C ++标准中的这个特定句子是从C标准中借用的。 C89标准中似乎存在相同的措辞,至少根据this unofficial version,并且存在于C99和C11中。

虽然C ++标准没有定义“外部声明或定义”,但这些术语在C标准中定义(引用N1256§6.9):

  

预处理后的程序文本单位是翻译单位,   它由一系列外部声明组成。这些是   被描述为“外部”,因为它们出现在任何功能之外(和   因此有文件范围)。 [...]

     

外部定义是外部声明,也是一个   函数或对象的定义。

翻译单元的C语法是:

translation-unit:
    external-declaration
    translation-unit external-declaration
external-declaration:
    function-definition
    declaration

现在,C ++标准中翻译单元的相应描述是(§3.5[basic.link]):

  

翻译单元由一系列声明组成。

语法只是

translation-unit:
    declaration-seq_opt

简而言之,在C中,翻译单元是外部声明的序列,而在C ++中,它是声明的序列。因此,似乎C ++标准中的“外部”一词是由借用引起的历史人工制品,引用的句子意味着禁止在任何声明或任何类型的定义中包括标准库头。