【问题标题】:Does C++ support Variable Length Arrays?C++ 是否支持可变长度数组?
【发布时间】:2012-01-25 11:46:27
【问题描述】:

不,等等,请耐心等待……

VLA 一直是 GCC 扩展,但被 C99 采用:

[C99: 6.7.5.2/4]:如果大小不存在,则数组类型为 不完整的类型。如果大小是 * 而不是表达式,则 数组类型是未指定大小的可变长度数组类型,它 只能在具有函数原型范围的声明中使用;这样的 数组仍然是完整的类型。 如果大小是整数 常量表达式并且元素类型具有已知的常量大小, 数组类型不是变长数组类型; 否则, 数组类型是变长数组类型。

C99 也称为ISO/IEC 9899:1999

现在:

[C++11: 1.1/2]: C++ 是一种基于通用编程语言 在 ISO/IEC 9899:1999 中指定的 C 编程语言上 (以下简称C标准)。除了 C 提供的工具,C++ 提供了额外的数据类型、类、 模板、异常、命名空间、运算符重载、函数名 重载、引用、免费存储管理操作符,以及 额外的图书馆设施。

那么 C++11 不应该也有 VLA 吗?

【问题讨论】:

  • 相关: stackoverflow.com/questions/1887097/variable-length-arrays-in-c (虽然我的问题实际上是关于从技术上说该功能首先不是从 C99 继承的;另一个是关于询问是否委员会可以明确地这样做)
  • 无论如何,我认为“基于 C 编程语言”是内容丰富的文本。 “除了 C 提供的设施”是指“除了 C 提供的一些设施并且我们将其合并到 C++ 中”,而不是“哦,如果有什么来自 C 的东西我们忘记在下面的文本中提及,那就是在 C++ 中”;-)
  • @Steve:好的。也许我当时遇到的问题是假设 C 语言以及 C 标准库默认情况下是从 C99“继承”的。也许它只是库,而语言只是被引用作为设计的基础。
  • 嗯,从 C 中获取的每个库函数都列在 C++ 标准中,引用 C99 标准说,“这个函数和那里的一样”,并且在一些案例“......具有以下区别”。所以我同意,没有批发继承,只是采摘 99% 的樱桃。
  • C99 VLA 与 GCC 的数组有不同的行为。 C99 没有采用 GCC 数组。

标签: c++ c++11 variable-length-array


【解决方案1】:

这种留有余地的措辞并不意味着 C99 中的任何东西都在 C++11 中。您引用的只是介绍性文字。

【讨论】:

  • 重温一下,我引用的内容是规范的,似乎在很大程度上暗示我 C++ 提供了the facilities provided by C
  • @LightnessRacesinOrbit 你从那句话中的具体内容推断出什么?陈述“A 基于 B”并不意味着 B 的每个特征都存在于 A 中。例如,“基于真实故事”的电影并不包含它所基于的真实故事的所有特征。而且,如果您“基于另一个提案”编写提案,则并不一定意味着其他提案具有的任何功能也在您的提案中。除非给出“基于”关系的正式定义,否则我将使用标准的日常含义。
  • 这不是“基于”的句子。是后面的那句话。 “除了 C 提供的功能之外,C++ 还提供...” 这意味着 C++ 至少提供了 C 提供的功能。
  • @light 我是为了好玩 :) 是的,我同意这意味着 C++ 有 VLA。但我不认为这是一个缺陷(如果有的话,它与后来使 VLA 格式错误的文本相矛盾,而不是允许 VLA)。介绍性段落故意不精确(作为警告,在 std-c++ usenet 组的“如何报告问题”页面上也提到了 IIRC)。
  • “(如果有的话,它与后来的文本相矛盾,使 VLA 格式不正确,而不是允许 VLA)” 正是这个问题的重点:)
【解决方案2】:

这个 C99 特性被 C++ 自己的语义有效地覆盖,任何其他“继承”的特性都可以:

[C++11: 8.3.4/1]:在 T D 的声明中,D 的格式为

D1 [ constant-expressionopt ] attribute-specifier-seqopt

[..]

这是我们在 C++ 中给出的唯一数组声明语法。

请注意,“与 C 的兼容性”子句 C.1 中没有提及这种差异。

【讨论】:

  • 我认为它甚至不是“覆盖”——C 功能在 C++ 中不是通过继承,而是通过组合和曝光而存在的。没有在 C++ 标准中明确提及的任何 C 功能,就好像 C++ 从 C 中“继承”了任何内容,只是巧合地包含了类似的文本。但作者显然有动力在可能的情况下提供 C 功能,并且他们认为自己不愚蠢。
  • int x = foo(); int n[x]; 算不算?这在 g++4.6 上对我有用。 x 这里肯定不是常量表达式吗?
  • @Aaron McDaid 如果你没有使用-pedantic(或者是-ansi?)进行编译,你可能得到了 g++ 扩展。
  • @MarkB, -pedantic 给了我“template.cpp:7:12: warning: ISO C++ forbids variable length array 'n' [-Wvla]” 我以前有 -Wall 和 -Wextra。
  • 从 GCC 的角度来看,与其说是“所有警告”,不如说是“你希望我编译什么语言”。如果您不说-pedantic,那么您不是在编译C++,而是在编译带有扩展的C++。如果您说std=gnu++0x,您会得到扩展,还有与标准相矛盾的语言更改,而不是有效地扩展它。我认为编译器编写者不会将其设为默认值,原因与他们认为首先扩展语言是个好主意的原因相同(傲慢和抱怨客户的结合)。
【解决方案3】:

两种语言对常量表达式的定义不同。

const size_t size = 5;
int array[size]; // array in C++, VLA in C

【讨论】:

  • @DrumM -- 你在说什么?添加评论时,您是否在考虑不同的答案(或问题?!)?让您投反对票的答案有什么问题?
  • 您的答案反映在 constexpr 上,这在 99% 的情况下是不可能的,当大小不是 const 时,人们使用可变长度数组,例如当它是一个输入变量时。因此,即使您从输入变量声明 const,它仍然不是编译时常量。 const size_t size = 5; 只是一个无用的额外行...
  • 首先,您所说的“这并不能解决警告”是什么意思?其次,我解释了 C 和 C++ 在两种语言中语法相同的行之间的细微差别。通过引入constexpr 并将const int 声明视为无用的额外行,您显然没有抓住重点。
【解决方案4】:

这是为我编译的:(g++ 4.6 with -std=c++0x)。但它不能用-pedantic 编译(感谢@MarkB)。相反,它警告说“template.cpp:7:12: warning: ISO C++ forbids variable length array ‘n’ [-Wvla]

int main(int argc, char ** argv) {
    int n[argc];
}

所以n 的大小在编译时无法被编译器知道。 这是对 C++ 的 GNU 扩展吗?这似乎是 GNU 扩展,而且 VLA 不是 C++11 的官方部分。

(当然,我只是在玩编译器。所以,请多加一点盐。)

【讨论】:

  • (a) GCC 也确实有 VLA 作为扩展。 (b) 在过去,我曾看到无法检测到数组维度何时是可变的。
  • 这是 g++ 扩展。如果您使用-pedantic 进行编译,它会警告它正在使用编译器扩展并且是不是 ISO C++。
猜你喜欢
  • 1970-01-01
  • 2011-12-13
  • 2018-07-05
  • 2018-10-03
  • 2014-07-14
  • 2021-04-12
  • 2018-05-14
  • 2018-06-27
相关资源
最近更新 更多