C99(及更高版本)7.1.3 保留标识符是否缺少 "external"?

Does C99 (and later) 7.1.3 Reserved identifiers miss "external"?

C89, 4.1.2 Standard headers(强调已加):

All external identifiers that begin with an underscore are reserved.

C99 (and later), 7.1.3 Reserved identifiers, 1(强调已加):

All identifiers that begin with an underscore are always reserved for use as identifiers with file scope in both the ordinary and tag name spaces.

C 的基本原理,7.1.3 保留标识符,25(强调已添加):

Also reserved for the implementor are all external identifiers beginning with an underscore, and all other identifiers beginning with an underscore followed by a capital letter or an underscore.

因此,根据 C99(及更高版本),在:

typedef int _t;        // non-reserved in C89, reserved in C99 (and later)
static int _f(int x);  // non-reserved in C89, reserved in C99 (and later)

(在文件范围内声明)_t_f 被保留,这与 Rationale 和 C89 相矛盾。

这是否意味着 C99(及更高版本)在 7.1.3 保留标识符中缺少“外部”:“所有 外部 标识符...”?

table:

                                is _x reserved ?

                                C89     C99 (and later)
scope - linkage
function - external             n/a     n/a
function - internal             n/a     n/a
function - none                 no      no
file - external                 yes     yes**
file - internal                 no      yes**
file - none                     no      yes**
block - external                yes     no*
block - internal                n/a     n/a
block - none                    no      no
function prototype - external   n/a     n/a
function prototype - internal   n/a     n/a
function prototype - none       no      no

其中 * 是一个可能的缺陷,请参阅 并且 ** 是“在普通名称空间和标记名称空间中”(C11,7.1.3 保留标识符,1) .

在这里我们看到 C99(及更高版本)保留更多(如果 table 是正确的)。额外:为了什么目的?

我认为 C89 和 C99 中的规则相同(即保留您的示例用法),但措辞已得到改进。转述:

  • 旧:“保留外部标识符[描述]”。
  • 新:“标识符 [description] 保留用于外部声明”。

标准甚至没有定义术语“外部标识符”;也许这是措辞改变的动机之一。

如果我们把“外部标识符”理解为“由外部声明声明的标识符”,那么规则是一样的。


注意:外部声明表示“具有文件作用域的声明”(C11 6.9/4);这经常与“带有外部链接的标识符声明”相混淆。

C89 标准确实使用了特定文本“带有外部链接的标识符”(例如 A.6.3.2),所以我认为“外部标识符”不应该表示“带有外部链接的标识符” .

Does C99 (and later) 7.1.3 Reserved identifiers miss "external"?

很明显,C99 和 C 的每个后续版本,直到并包括当前最新的 C17,省略 您所询问的条款中的“外部”限定。这不一定构成他们文本中的缺陷。

So, per C99 (and later), in:

typedef int _t;        // non-reserved in C89, reserved in C99 (and later)
static int _f(int x);  // non-reserved in C89, reserved in C99 (and later)

(declared at file scope) the _t and _f are reserved, which contradicts with Rationale and with C89.

是的,那些出现在文件范围内的声明分别声明了没有 linkage 和内部 linkage 的 _t_f。它们不是外部标识符(尽管它们在 外部声明 中声明),因此 C89 不保留它们用于该用途。另一方面,C99 及更高版本 do 保留它们供该用途使用。

“矛盾”对于这种差异来说太强烈了。是的,C99 保留了一些 C89 没有的标识符用法(反之亦然)。这不是两者之间唯一的向后不兼容。 C99“取消并取代”了C89,因此前者不需要与后者的所有细节一致。

至于原理,是的,解释的是C89版本的保留,不是C99的形式。我认为那个是理由上的缺陷,毕竟不规范。

Does it mean that C99 (and later) misses "external" in 7.1.3 Reserved identifiers: "All external identifiers that ..."?

我认为没有理由断定 C99 及更高版本中该条款中省略“外部”代表编辑错误。事实上,我将周围文本的相应更改作为更改是有意更改的证据。特别是,C89 文本继续“所有 other 标识符以下划线和 upper-case 字母或另一个下划线开头”(强调已添加),而 C99 和更高版本删除“其他”也是如此。据我所知,C99 打算保留比 C89 更多的标识符使用。

但是这里 一个可能的缺陷,因为 C89 保留了一些标识符使用,而 C99 没有,但可能打算这样做。这些是外部标识符 在块范围 下划线开头,不紧跟大写字母或另一个下划线。示例:

int f(void) {
    extern int _var;
    extern int _func(int);

    // ...
}

_var_func 的那些用法在 C89 中保留,但在 C99 及更高版本中不保留。符合标准的 C 代码无法为这些标识符提供 link 的定义,因为规范的所有版本中的标识符保留都不允许这样做,但它们可能与实现定义的外部标识符发生冲突。