【问题标题】:Does "int size = 10;" yield a constant expression?是否“int size = 10;”产生一个常量表达式?
【发布时间】:2014-02-11 23:22:16
【问题描述】:

以下代码在 gcc 4.8 和 Clang 3.2 下编译:

int main()
{
  int size = 10;
  int arr[size];
}

C++ 标准的 8.3.4/1 规定数组的大小必须是整数常量表达式,size 似乎不是。这是两个编译器中的错误,还是我遗漏了什么?

最新的 VC++ CTP 拒绝带有这个有趣消息的代码:

error C2466: cannot allocate an array of constant size 0

有趣的部分是它似乎认为size 是零。但至少它拒绝了代码。 gcc 和 Clang 不应该做同样的事情吗?

【问题讨论】:

  • 可变长度数组仅是 C 而不是 C++。但是,gcc 和 clang 支持它作为扩展。
  • 可能是 C++1y 和/或 C99 中提出的可变长度数组的扩展?
  • std::valarray 在 C++1y 中提出
  • @BryanChen,您可能正在考虑 std::dynarray,但它和 VLA 都在 TS AFAIK 中。
  • 这是我一段时间以来回答的更有成效的问题之一。在试图加强我对常量表达式的回答时,我发现了一个关于未定义行为的花絮,这导致我提出了这个问答Why do constant expressions have an exclusion for undefined behavior?

标签: c++ arrays c++11 compile-time-constant variable-length-array


【解决方案1】:

这是variable length arraysVLA,这是一个C99 功能,但gccclang 支持它作为C++ 中的扩展> 而 Visual Studio does not。所以Visual Studio 在这种情况下遵守标准并且在技术上是正确的。并不是说扩展不好,Linux kernel depends on many gcc extensions,所以它们在某些情况下很有用。

如果您添加 -pedantic 标志,gccclang 都会对此发出警告,例如 gcc 表示 (see it live):

warning: ISO C++ forbids variable length array 'arr' [-Wvla]
  int arr[size];
              ^

使用-pedantic-errors 标志会使这成为错误。您可以在这些文档 Language Standards Supported by GCCclangs Language Compatibility section 中阅读有关扩展的更多信息。

更新

draft C++ standard5.19 常量表达式 段落3 中涵盖了整数常量表达式 并说:

整型常量表达式是整型或无作用域枚举类型的表达式,隐式转换为纯右值,其中转换后的表达式是核心常量表达式。 [...]

阅读本文并不能直观地看出所有可能性,但 Boost's Coding Guidelines for Integral Constant Expressions 在这方面做得很好。

在这种情况下,由于您使用 const 使用 literal 初始化 size,因此足以使其成为 整数常量表达式(请参阅[expr.const]p2.9.1) 并将代码恢复为标准 C++:

const int size = 10;

使用 constexpr 也可以:

constexpr int size = 10;

阅读Difference between constexpr and const 可能会有所帮助。

对于C99 draft standard 中与8.3.4 段落1 等效的部分,将是6.7.5.2 部分数组声明符 段落4上面写着(强调我的):

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

【讨论】:

    猜你喜欢
    • 2015-10-10
    • 1970-01-01
    • 2020-06-23
    • 2016-03-01
    • 2017-08-20
    • 1970-01-01
    • 2018-06-01
    • 1970-01-01
    • 2012-01-02
    相关资源
    最近更新 更多