为什么C ++函数可以创建可变长度的数组?

时间:2022-05-31 21:22:02

According to this answer, which states:

根据这个答案,其中指出:

The compiler knows the size of the int type and therefore can generate the right assembler instruction that will reserve enough space on the stack in order to let foo live there.

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

a compiler needs to know the size a function will occupy on the stack in order to implement it.

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

Then, why does this code compile?

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

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

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

x is an array of integers, but its size isn't constant, it can change any time the function is called.

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

What am I missing here?

我在这里想念的是什么?

3 个解决方案

#1


8  

This is not legal code in Standard C++. It compiles thanks to an extension specific to your compiler which supports variable-length arrays, which is a C99 feature.

这不是标准C ++中的合法代码。它由编译器特有的扩展编译,支持可变长度数组,这是一个C99功能。

But again, this is not portable C++. If you need dynamic sizing, you could rewrite your function this way:

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

#include <vector>

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

Otherwise, make it a template and write it this way:

否则,将其设为模板并以这种方式编写:

#include <array>

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

#2


4  

It compiles because you're using a non-standard extension. In the strict sense, it's not valid C++, but some compilers do support this.

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

In your case (3 and 5 are known), you can use templates instead, which would be valid, or directly a std::vector.

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

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

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

#3


0  

The compiler's job is indeed harder in this case. It now needs to emit code which will - at runtime - figure out how much memory is needed (n*sizeof(int)), and where to get that memory from. That memory is still released at the same place as where int y[5]; would be released, so in that respect nothing changes.

在这种情况下,编译器的工作确实更难。它现在需要发出代码,这些代码将在运行时计算出需要多少内存(n * sizeof(int)),以及从哪里获取内存。那个记忆仍然和int y [5]在同一个地方发布;将被释放,所以在这方面没有任何变化。

One easy solution for the compiler is to change the code behind the scenes to int * __x = malloc(n*sizeof(int) ... free(__x). It might also need to rewrite some code for sizeof(x), but there too the compiler can rewrite the VLA code to "normal" code. There is no magic needed; VLA's can be implemented as mere syntactic sugar.

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

#1


8  

This is not legal code in Standard C++. It compiles thanks to an extension specific to your compiler which supports variable-length arrays, which is a C99 feature.

这不是标准C ++中的合法代码。它由编译器特有的扩展编译,支持可变长度数组,这是一个C99功能。

But again, this is not portable C++. If you need dynamic sizing, you could rewrite your function this way:

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

#include <vector>

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

Otherwise, make it a template and write it this way:

否则,将其设为模板并以这种方式编写:

#include <array>

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

#2


4  

It compiles because you're using a non-standard extension. In the strict sense, it's not valid C++, but some compilers do support this.

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

In your case (3 and 5 are known), you can use templates instead, which would be valid, or directly a std::vector.

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

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

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

#3


0  

The compiler's job is indeed harder in this case. It now needs to emit code which will - at runtime - figure out how much memory is needed (n*sizeof(int)), and where to get that memory from. That memory is still released at the same place as where int y[5]; would be released, so in that respect nothing changes.

在这种情况下,编译器的工作确实更难。它现在需要发出代码,这些代码将在运行时计算出需要多少内存(n * sizeof(int)),以及从哪里获取内存。那个记忆仍然和int y [5]在同一个地方发布;将被释放,所以在这方面没有任何变化。

One easy solution for the compiler is to change the code behind the scenes to int * __x = malloc(n*sizeof(int) ... free(__x). It might also need to rewrite some code for sizeof(x), but there too the compiler can rewrite the VLA code to "normal" code. There is no magic needed; VLA's can be implemented as mere syntactic sugar.

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