【问题标题】:If a compiler defines __STDC_NO_VLA__, does it still have to support flexible array members?如果编译器定义了 __STDC_NO_VLA__,它是否还必须支持灵活的数组成员?
【发布时间】:2018-12-10 00:00:31
【问题描述】:

在 C99 中,(结构的)灵活数组成员和可变长度数组是标准的强制性部分——符合 C99 的编译器(实现)必须同时支持它们。

在 C11 中,允许定义 (§6.10.8.3 Conditional feature macros):

__STDC_NO_VLA__ 整数常量 1,用于表示 实现不支持可变长度数组或可变 修改类型。

我没有在标准中发现任何地方规定具有 FAM 的结构是可变修改类型,因此我认为即使不支持 VLA,也需要 C11 编译器来支持 FAM。支持这种解释的一项:具有 FAM 的结构的大小是固定的; FAM 不计入大小的一部分(而 VLA 的大小不是编译时常量)。

【问题讨论】:

  • 我不明白为什么要支持 VLA 和灵活的数组成员。
  • @alk:就标准而言,我认为它们并不相关,但它们都涉及在运行时确定大小的数组(malloc() 等的许多用途也是如此)。我正要为 VLA 类型和带有 FAM 的结构类型的“类型大小”打印程序添加一些代码,并想知道 __STDC_NO_VLA__ 是否意味着应该不测试 FAM 代码。
  • 只是出于病态的兴趣:您是否遇到过不支持灵活数组成员的现代 C 编译器? (我希望你没有,问题是通过其他方式提出的。)
  • @NominalAnimal — 不,但我没有尝试过最近的 Microsoft 编译器。与旧版本相比,它们对 C99(可能还有 C11)有更好的支持,但我不确定它们与任一标准有多接近,或者它们的宏定义声称支持什么。
  • 啊,对。我更多地考虑了各种嵌入式 C 编译器。 (正如我在其他讨论中提到的,我不再对 MS 编译器产品甚至 C 标准的未来版本抱有任何信任或希望。)

标签: c language-lawyer c11 variable-length-array flexible-array-member


【解决方案1】:

好吧,说白了,标准并没有说 FAM 是可选的,所以 FAM 不是可选的。

不过,更进一步,标准委员会似乎不太可能费心接受不支持 FAM 的实现。与 VLA 相比,添加对灵活数组的支持是微不足道的——稍微调整一下解析器,允许结构的最后一个成员是大小为零的数组,然后就结束了。 VLA 需要更复杂的静态分析,并且在一些小型独立架构中可能会很繁重或无法实现。

【讨论】:

  • 顺便说一句,我希望委员会有智慧只将声明具有 VLA 类型的对象作为可选功能,同时强制支持可变修改类型。这将允许 VLA 的主要实际用途,即指向 VLA 的指针。
  • @R.. 完全同意。在我看来,这是 C11 的一个缺陷。指向 VLA 的指针是现代 C 编程中的一个重要特性。实际分配的 VLA 实例:没有那么多。
  • @R..:恕我直言,他们应该有一个三向宏来表示支持 VLA 实例、VLA 类型但不支持实例,或者两者都不支持。即使目标平台在支持 VLA 类型方面没有特别的问题,为编译器添加支持也需要增加相当多的额外复杂性。如果编译器永远不会用于任何需要 VLA 类型的程序,那么这种复杂性将完全是浪费。
  • @R..: 或者,换一种说法,支持编译器的用户客户想要的可选功能应该被视为质量指标,但支持客户不关心的功能不应该。
  • pointer-to-VAL 确实是一件非常“好东西”。它并没有解决它的不足,但我很好奇为什么没有人在这里提到alloca?也许作为 VLA 的穷人替代品?
【解决方案2】:

灵活的数组成员支持应该独立于 VLA 支持。事实上,在 C99 标准命名之前,可以通过在 struct 末尾声明一个长度为零的数组来使用灵活的数组成员。

基本上,要支持灵活的数组成员,您唯一需要做的就是更改编译器以支持flexible[] 语法。

相比之下,支持 VLA 需要更多的努力:

  • 编译时可能不再进行自动分配
  • 必须更改 sizeof 运算符以支持运行时评估
  • 必须设计一个特殊的结构来保持数组的大小可用

这些实现点可能足以让编译器设计者决定不实现 VLA。

【讨论】:

  • C99 之前的 struct hack 技术通常涉及大小为 1 的数组。GCC 可能允许大小为 0 的数组;即使标准没有,它仍然有效。
  • @JonathanLeffler:在 C89 之前,很多编译器都接受零大小的数组,因为程序员使用它们比破解大小为 1 的数组的怪癖更容易。 C99 增加的灵活数组成员只不过是恢复了一个本来就不应该被删除的特性。
猜你喜欢
  • 2018-02-24
  • 1970-01-01
  • 2011-08-16
  • 1970-01-01
  • 2013-02-19
  • 1970-01-01
  • 2012-01-24
  • 1970-01-01
  • 2018-12-15
相关资源
最近更新 更多