【问题标题】:Why can C++ functions create arrays of variable lengths?为什么 C++ 函数可以创建可变长度的数组?
【发布时间】:2013-03-31 00:38:21
【问题描述】:

根据this answer,其中规定:

编译器知道 int 类型的大小,因此可以生成 正确的汇编指令将保留足够的空间 堆栈以便让 foo 住在那里。

编译器需要知道函数在堆栈上占用的大小才能实现它。

那么,这段代码为什么会编译呢?

int f(int n)
{
    int x[n];
}

int main()
{
    f(3);
    f(5);
    //etc
}

x 是一个整数数组,但它的大小不是恒定的,它可以在函数被调用的任何时候改变。

我在这里错过了什么?

【问题讨论】:

  • -pedantic再次编译。
  • "erw.cpp: In function 'int f(int)': erw.cpp:3:12: warning: ISO C++ forbids variable length array 'x' [-Wvla]" - @chris : 谢谢,现在说得通了。
  • 在堆栈上为 x 分配空间只是从 esp(堆栈指针)中减去 sizeof(int)*n 的问题。语义是问题 - 就像初始化枚举 {Ok = sizeof(x)} 的情况一样。可能直到出现禁止的语义使用,您的编译器才允许此类使用。
  • @MSalters:抱歉,回滚了。问题是关于 C++,而不是 C99,Luchian Grigore 的回答和我的回答都是针对这类问题(“为什么我可以这样做,为什么它会编译?这不是非法的吗?”)。尽管“编译器如何实现 VLA”这个问题也很有趣,但这并不是 OP 最初的意思。

标签: c++ arrays function memory integer


【解决方案1】:

它编译是因为您使用的是非标准扩展。从严格意义上讲,它不是有效的 C++,但一些编译器确实支持这一点。

在您的情况下(已知 3 和 5),您可以改用模板,这将是有效的,或者直接使用 std::vector

template<int n>
int f()
{
    int x[n];
}

//...
f<3>();

【讨论】:

    【解决方案2】:

    这不是标准 C++ 中的合法代码。它的编译得益于特定于您的编译器的扩展,该扩展支持 variable-length arrays,这是 C99 功能。

    但同样,这不是可移植的 C++。如果你需要动态调整大小,你可以这样重写你的函数:

    #include <vector>
    
    int f(int n)
    {
        std::vector<int> v(n);
    }
    

    要不然就做成模板,这样写:

    #include <array>
    
    template<std::size_t N>
    int f()
    {
        std::array<int, N> a;
    }
    

    【讨论】:

      【解决方案3】:

      在这种情况下,编译器的工作确实更难。它现在需要发出代码,这些代码将在运行时确定需要多少内存 (n*sizeof(int)),以及从哪里获取该内存。该内存仍会在 int y[5]; 将被释放的位置释放,因此在这方面没有任何变化。

      编译器的一个简单解决方案是将幕后代码更改为int * __x = malloc(n*sizeof(int) ... free(__x)。它可能还需要为sizeof(x) 重写一些代码,但是编译器也可以将 VLA 代码重写为“正常”代码。不需要魔法; VLA 可以仅作为语法糖来实现。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-01
        • 2014-07-27
        • 2021-07-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多