2013-04-08 94 views
5

this answer,其中规定:为什么C++函数可以创建可变长度的数组?

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

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

那么,为什么这个代码编译?

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

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

x是一个整数数组,但它的尺寸不是恒定的,它可以改变的任何时间被调用的函数。

我在这里错过了什么?

+5

用'-pedantic'再次编译它。 – chris 2013-04-08 19:39:06

+1

“erw.cpp:In function'int f(int)': erw.cpp:3:12:warning:ISO C++禁止变长数组'x'[-Wvla]” - @chris:谢谢,这很有道理现在。 – corazza 2013-04-08 19:40:36

+0

[在C++书中,数组绑定必须是常量表达式,但为什么下面的代码有效?](http://stackoverflow.com/questions/5947661/in-c-books-array-bound-must-be -constant-expression-but-why-the-following-cod) – 2013-04-08 19:58:07

回答

8

这不是标准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; 
} 
4

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

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

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

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

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

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

相关问题