“外部声明或定义”不是我所想的吗?

Does "external declaration or definition" not mean what I think?

提问人:Luchian Grigore 提问时间:5/12/2013 更新时间:9/3/2014 访问量:215

问:

17.6.2.2 标头 [using.headers]

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

如果我的解释是正确的:

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

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

我是不是误读了?“外部声明”和“外部定义”是否意味着其他含义(在这种情况下)?

C++ 头文件 language-lawyer

评论

0赞 Stefano Sanfilippo 5/12/2013
那个头文件来自 libsmth 吗?smth.h
0赞 Luchian Grigore 5/12/2013
@StefanoSanfilippo没有:)对不起:)
0赞 Mat 5/12/2013
链接规范不是外部声明吗?extern "C"
0赞 Luchian Grigore 5/12/2013
@Mat 我的想法正是如此,但我看不出在这种情况下“外部声明”可能意味着什么。
0赞 Joseph Mansfield 5/12/2013
@LuchianGrigore我同意它一定是这个意思。这个意思也是有道理的。

答:

4赞 Joseph Mansfield 5/12/2013 #1

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

C++ 标准库的每个元素都在标头中声明或定义(根据需要)。

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

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

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

extern "C"
{
   #include <string>
}

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

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

我认为这种措辞的目的是将标准库标头与其表示方式分离。没有理由必须将它们存储为 C++ 源文件,即使它们通常是。包含特定的标头只需要具有向程序提供适当声明的效果。

评论

0赞 Luchian Grigore 5/12/2013
好吧,引号说的是“标题”,而不是“库标题”。不是说你错了,而是你的论证不完整。
0赞 Joseph Mansfield 5/12/2013
@LuchianGrigore “header”上的斜体在标准中,这意味着它是单词的定义。据我所知,标头包括 C++ 库标头和 C 库工具的 C++ 标头(而不是附录 D 中单独定义的 C 标头)。
0赞 Luchian Grigore 5/12/2013
这是否也意味着它是排他性的?即“C++标准库的每个元素都在标头中声明或定义(视情况而定)”=> 标头中不能定义其他元素/不存在其他标头?
0赞 Joseph Mansfield 5/12/2013
@LuchianGrigore我认为这是值得商榷的,但规范有助于支持它。#include
0赞 Luchian Grigore 5/12/2013
是的,您的编辑很有意义。我猜有点误导(标准中的措辞)。
1赞 T.C. 9/3/2014 #2

我认为约瑟夫·曼斯菲尔德(Joseph Mansfield)的回答基本上正确地解释了“头”一词(它仅指§17.6.1.2 [头文件]中定义的标准库头文件),但我认为它还包括附录D中描述的C头文件,因为脚注176(在N3936中)将两者称为“标准头文件”。这个答案侧重于短语外部声明或定义的含义。<iso646.h><ciso646>

C++标准中的这个特定句子似乎是从C标准借来的。C89 标准中似乎存在相同的措辞,至少根据这个非官方版本,并且存在于 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++ 标准中的“外部”一词似乎是由借用引起的历史产物,引用的句子旨在禁止在任何类型的声明或定义中包含标准库头。