4

(这个问题是由上一个问题的答案提示的)

C11 标准在讨论兼容编译器应该能够支持的程序的复杂性时使用了以下公式:

5.2.4.1 翻译限制

实现应能够翻译和执行至少一个程序,该程序包含以下每个限制的至少一个实例:

...

  • 一个函数调用中有 127 个参数

...

这个“至少一个”的措辞对我来说似乎很奇怪,因为它看起来像一个符合标准的程序可以对大多数用法施加任意限制并且仍然是合规的。例如,可变参数函数的参数限制为 63 个,而具有显式参数的函数的参数限制为 127 个。或者要求只有名称以“BIGARG_”开头的函数才能调用超过 99 个参数。或者其他一些这样的限制。

即使有潜在的任意限制,也可能存在一些奇怪的情况,即支持 127 个参数限制,因此可以翻译和执行至少一个包含该限制的至少一个实例的程序。只是并非所有(甚至大多数)接近该限制的程序都将得到支持。

这种特殊的措辞是否有理由?为什么不明确要求支持遵守这些限制的每个程序(否则兼容)?或者是否有其他机制需要统一支持,例如函数调用中的 127 个参数?

4

2 回答 2

3

该标准不能要求实现接受所有此类兼容程序。考虑几个限制,比如 127 个嵌套级别的块和 511 个具有块范围的标识符。现在想象一个程序,它有 127 层嵌套块每一层都有 511 个标识符。在每个标识符中加入 63 个有效字符,您就拥有了一个庞大的程序。在 16 位微型计算机上运行的实现,比如 PDP-7 :) 可能无法应对它。

于 2016-02-27T19:47:17.573 回答
3

是的,一个实现可以对它可以处理的程序施加任意限制,同时仍然符合标准的字母。但 5.2.4.1 的意图是满足其特定要求的最简单方法是支持所有程序的合理限制。

您可以创建一个单个程序来满足 5.2.4.1 中定义的每个翻译限制(例如,不产生输出),然后编写一个“编译器”来识别该单个程序并生成一个可执行文件的int main(void){},同时拒绝所有其他程序并带有诊断消息,指出它超出了实现的翻译限制。

当然,这样的编译器完全没有用,这就是为什么(据我所知)没有人费心去创建这样的东西。(我想过自己做,只是为了它。)

在实践中,编译器编写者希望生成能够正确编译真实 C 代码的有用编译器。

5.2.4.1 的要求旨在满足它们的最简单方法(如果您正在编写有用的 C 编译器)是施加尽可能少的实际限制。

例如,一个符合标准的编译器必须支持这个神话般的“一个程序”的 127 个嵌套级别的块。满足该要求的最简单方法是通过让编译器使用动态数据结构来支持任意深度的嵌套块。实际上,深度受到限制,不是由编译器源代码中的硬连线限制,而是由编译时可用的内存量限制。(或者编译器可以使用一些固定大小的内部数据结构,该结构正好允许127 个级别,但允许动态大小可能更容易。)

您可能认为标准强加更“合理”的要求会更好,以便符合标准的编译器必须接受所有不超过某些指定限制的程序。问题是这种“合理”的限制是极其难以精确指定的。总会有一些程序超出编译器的能力——这些程序的大小或复杂性取决于编译器使用的内部数据结构和算法,以及编译器运行的特定系统的能力上。该标准无法涵盖这些细节,或预测未来系统可能“合理”的限制。

于 2016-02-27T19:41:36.717 回答