GCC 如何在堆栈上创建一个数组而不用常量变量给出其大小?

How does GCC create an array on the stack without its size being given by a constant variable?

这个例子如何编译和运行?

#include <iostream>

int main() {
    int input;
    std::cin >> input;
    int arr[input];
    return 0;
}

我的理解是,由于 input 的值在编译期间是未知的,所以它必须是堆分配数组。程序启动时,数组之类的东西(没有在堆上分配)的堆栈space不是分配的吗?

My understanding is that since the input's value is not known during compile time, it'd have to be a heap allocated array.

你的理解是正确的。

Isn't the stack space for things like arrays (without allocating on the heap) allocated when the program starts?

在实践中,执行栈的内存通常是在程序启动时分配的。这不是 C++ 语言指定的内容,而是实现细节。

How does this example compile and run?

程序格式错误。编译器不需要编译程序并且需要诊断问题(如果它不诊断它,那么编译器不符合 C++ 标准)。编译器仍然可以将程序编译为语言扩展。 C++ 语言没有指定这是如何发生的。

My understanding is that since the input's value is not known during compile time, it'd have to be a heap allocated array.

虽然 C++ 语言规则确实说你不能这样做,但从调用堆栈通常如何实现的技术角度来看,这实际上不一定是正确的。一般来说,是的,事先不知道大小的对象不会放在堆栈上。然而,在局部变量是可变长度数组的情况下,编译器将该数组放入堆栈 space 并不难。例如,C 语言支持这一点,this older question 解决了一种实现方式。尽管 C++ 不允许像 C 那样使用可变长度数组(从技术上讲,您这里的代码不是合法的 C++ 代码),但一些编译器允许它。

Isn't the stack space for things like arrays (without allocating on the heap) allocated when the program starts?

通常情况并非如此。当程序启动时,它会被分配一个内存区域并被告知“这是你的堆栈应该去的地方”,但是 space 通常不由程序的编写方式决定,通常由 OS 或由编译器设置。然后,每当需要堆栈上的 space 时——比如说,因为调用了一个函数或因为进入了一个新的块作用域——程序在调用堆栈上占用了一些 space,当块作用域退出或函数 returns.

因此,程序不需要在开始时就知道为每个函数在堆栈上保留多少 space。它可以推迟到实际函数被调用。