允许运行时没有动态分配的数组大小?[复制]

Array size at run time without dynamic allocation is allowed? [duplicate]

提问人:syaz 提问时间:4/10/2009 最后编辑:cigiensyaz 更新时间:2/6/2023 访问量:64030

问:

我已经使用 C++ 几年了,今天我看到了一些代码,但这怎么可能是完全合法的呢?

int main(int argc, char **argv)
{
    size_t size;
    cin >> size;
    int array[size];
    for(size_t i = 0; i < size; i++)
    {
        array[i] = i;
        cout << i << endl;
    }

    return 0;
}

根据 GCC 编译。

如何在运行时没有 or 的情况下确定大小?newmalloc

只是为了仔细检查,我已经用谷歌搜索了一些,所有与我的代码相似的代码都声称会给出存储大小错误。

甚至Deitel的C++如何编程第261页也指出了常见编程错误4.5:

只能使用常量来声明自动数组和静态数组的大小。

照亮我。

c++ 数组初始化

评论

3赞 4/10/2009
请注意,DMA 的意思是“直接内存访问”——我想你问的是动态分配
3赞 Lightness Races in Orbit 4/10/2015
C 还是 C++?选择一个
1赞 5/10/2016
再次选择一个:C 或 C++。这个问题明确且仅与 C 有关;不应该有 C++ 标签。
0赞 Vadzim 11/7/2018
另请参阅为什么可变长度数组不是 C++ 标准的一部分?

答:

75赞 Mehrdad Afshari 4/10/2009 #1

这在 C99 中有效。

C99 标准支持堆栈上可变大小的阵列。可能您的编译器也选择支持此构造。

请注意,这与 和 不同。 在堆栈上分配数组,就像它通过调整堆栈指针一样。不进行堆分配。这很像_allocamallocnewgccint array[100]

评论

14赞 Jeff Lamb 1/13/2011
我在几个月前编写的代码库中的一个文件中遇到了同样的情况。我和团队的其他成员一样,对它为什么要编译感到困惑。在我们的情况中,数组的大小也是在声明数组之前计算的(这也不应该被允许?无论如何,一个挑战消失了。任何能回答为什么这是合法的人都会得到一个流行馅饼。如果你曾经在西雅图,请告诉我。我给你准备了一个流行馅饼。
2赞 balki 7/6/2011
在这种情况下,您能否提供有关堆栈内部如何工作的一些信息/链接?这会在运行时引入一些开销吗?
2赞 Mehrdad Afshari 7/7/2011
@balki 开销很小,因为它基本上是递增/递减堆栈指针。如果将原始堆栈指针保存在函数的开头,则堆栈行为可以与正常情况基本相同。
0赞 justpraveen 1/11/2015
这在 C++ 中是允许的吗?Visual Studio 不允许这样做?
0赞 torez233 12/5/2022
我不明白的是,当汇编程序生成汇编代码时,它当时并不知道数组的确切大小。那么,为了给这个动态大小的数组腾出空间,它要移动堆栈指针多少偏移量呢?它不能说。因此,了解这是如何实现的非常有趣
7赞 Özgür 4/10/2009 #2

它仅在 C99 中有效。下次您可以尝试在可靠的编译器中检查您的代码。

6赞 anon 4/10/2009 #3

它是有效的 C99,它不是有效的 C++。这是两种语言之间的不少差异之一。

评论

2赞 Mehrdad Afshari 4/10/2009
我想它将在C++0x中得到支持
0赞 4/10/2009
不符合标准草案第8.3.4节。
3赞 Johannes Schaub - litb 4/10/2009
它永远不会包含在 C++1x :D 中但让我们希望 dynarray<T> 能进来。我会喜欢的。所以你可以做dynarray<int> a(some_size);并让它有效地分配,可能使用编译器 hax 等_alloca等等。
3赞 Red XIII 8/29/2013
对于未来的任何人:它将包含在 C++14 中(具有较小的功能集,例如 sizeof() 等)。typedef
2赞 magras 1/27/2016
@RedXIII:猜错了。VLA 和 C++ 的一部分都不是 14。dynarray
27赞 jpalecek 4/10/2009 #4

这称为 VLA(可变长度阵列)。它在 c99 中是标准的,但 gcc 允许它在 c++ 代码中作为扩展。如果希望它拒绝代码,请尝试使用 和 选项。-std=standard-ansi-pedantic

评论

2赞 Jonathan Wakely 12/13/2018
和 选项与此扩展完全无关。-std-ansi
1赞 Najeeb 3/5/2013 #5

如果您使用的是 Dev-Cpp 编译器,您可以动态地为数组指定大小,我已经尝试过了 并且没有错误,但在 Visual C++ 和 Visual Studio 编译器上这是不可能的。 我认为原因是 dev-c++ 为未初始化的 int 分配了一个正数 当我们给它一个数字时,它就会被给定的数字所取代。 但也许其他编译器为未初始化的变量提供 null。

评论

0赞 jerry 5/22/2013
大多数编译器不会为未初始化的局部变量分配任何内容,它们通常会保留它们占用的内存中的任何内容,直到它们被程序分配。您引用的 Dev-C++ 似乎是 MinGW 之上的 IDE,其中包括一个 GCC 端口作为编译器。如其他答案所述,VLA 不是标准的 C++,但一些编译器(包括 g++)仍然支持它们。
0赞 Elkvis 10/13/2014
Dev-C++ 不是编译器。Visual Studio 也不是。Dev-C++ 使用 GCC/G++ 作为其编译器,而 Visual Studio 使用 cl(Microsoft 的编译器后端)。Dev-C++ 和 Visual Studio 本身就是集成开发环境 (IDE)。这是一个重要的区别。Dev-C++ 不会“分配”任何东西。编译器会这样做。
0赞 Elkvis 10/13/2014 #6

C++14 标准支持可变长度阵列 (VLA),该标准最近已被接受,正在等待发布。

评论

2赞 Jason 11/19/2015
VLA 仍然不是标准的一部分。有一个 dynarray TS,但到目前为止还没有被批准。
2赞 Dungeon 9/4/2015 #7

此代码在 GNU GCC 编译器中运行。

#include<bits/stdc++.h>

int main(int argc, char **argv)

{
    size_t size;

   std:: cin >> size;

    int array[size];

    for(size_t i = 0; i < size; i++)

{

array[i] = i;

        std:: cout << i;

 }

    return 0;
}
1赞 landerlyoung 10/21/2019 #8

我最近遇到了一个需要堆栈分配阵列的场景。(它是 v8 的包装器,每个方法调用都需要一个参数数组)。

std::vector 将执行堆内存分配,其性能是不可接受的。

这是我的解决方案,使用模板来分配案例数组:

template<size_t Argc>
static void call(...) {
    v8::Local<v8::Value> v8Args[Argc];

    // use v8Args
    ...
}

template<typename It>
static void callV8Function(size_t argc, It argvBegin, It argvEnd,) {
    // C++ don't have dynamic stack allocation (like C99 does)
    // try to avoid heap-allocation...
    if (argc <= 4) {
        return callV8FunctionOnStack<4>(...);
    } else if (argc <= 8) {
        return callV8FunctionOnStack<8>(...);
    } else if (argc <= 16) {
        return callV8FunctionOnStack<16>(...);
    } else if (argc <= 32) {
        return callV8FunctionOnStack< 32>(...);
    } else {
        std::vector<v8::Local<v8::Value>> v8Args(argc);
        // fallback to vector
   }
}

(当然,我可以只使用一个 32 大小的数组,但它不是那么优雅。