4

后续问题为什么一致的实现在具有内部链接的不完整数组类型中表现不同?.

上下文:默认情况下,在 gcc 和 clang(一致的实现)中,要求 C11,6.9.2p3 [1] 被取消,它被定位为扩展。

问题:扩展可以取消现有的标准要求,同时保持实施符合吗?

[1] C11,6.9.2 外部对象定义,3:

如果对象标识符的声明是一个暂定定义并且具有内部链接,则声明的类型不应是不完整的类型。

UPD。是的。换句话说:标准说:“我们不支持这一点,需要诊断”。扩展名说:“我们确实支持这一点(因此,标准所需的诊断是无关紧要的)”。

4

2 回答 2

2

实现并不是通过扩展“取消”需求,而是扩展添加了标准不支持的功能。主要要求是扩展不会改变任何严格符合的程序

符合C11 标准的第 4p6 节的定义如下:

两种形式的一致性实现是托管的和独立的。符合要求的托管实现应接受任何严格符合要求的程序。符合标准的独立实现应接受任何严格符合标准的程序,其中库条款(第 7 条)中指定的功能的使用仅限于标准头文件的内容 [...为简洁而省略...]。 一个符合要求的实现可以有扩展(包括额外的库函数),只要它们不改变任何严格符合的程序的行为

如果第 4p5 节中定义了严格符合的程序:

严格遵守的程序应仅使用本国际标准中指定的语言和库的那些特性。它不应产生依赖于任何未指定、未定义或实现定义的行为的输出,并且不应超过任何最小实现限制

第 4p7 节定义了一个符合要求的程序:

符合标准的程序是符合标准的实现可接受的程序。

因此,鉴于您之前的问题中的程序案例:

static int arr[ ];

int main( void )
{
        return arr[ 0 ];
}

static int arr[ ] = { 0 };

这不是一个严格遵守的程序,因为它违反了 6.9.2p3。然而,诸如 gcc 之类的一些实现允许将其作为扩展。支持这样的功能并不会阻止类似的严格遵守的程序,例如

static int arr[1];

int main( void )
{
        return arr[ 0 ];
}

static int arr[ ] = { 0 };

从行为上有所不同。因此,支持此功能的实现仍然有资格作为符合标准的实现。这也意味着第一个程序虽然不是严格符合的程序,但它是符合程序的,因为它将在符合要求的实现上以明确定义的方式运行。

于 2021-08-06T17:30:52.093 回答
2

该标准要求,如果程序违反了约束部分中的约束,则实现必须发出至少一个诊断。对于文档是否有意义或与约束违规有任何关系没有要求。无条件输出“警告:此实现不尝试将其作者认为是愚蠢的约束”的实现就足够了。同样,一个实现包括一个命令行选项来输出这样的消息和文档,除非指定了该选项,否则它可能不符合要求。

请注意,即使该要求也存在漏洞:如果程序超出实现的翻译限制,则该实现可以以任何方式运行,不受限制,并且不必发出任何类型的诊断。尽管标准要求每个实现必须至少存在一个源程序,该源程序至少名义上行使标准中给出的翻译限制而不会导致实现发生故障,但实现可能会对翻译限制如何交互施加任意限制,例如允许程序要么包含一个最多 63 个字符的标识符,要么包含大量不超过三个字符的标识符。

于 2021-08-06T17:07:07.673 回答