在运行时允许数组大小而不进行动态分配吗?


73

我已经使用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下编译。

没有newmalloc如何在运行时确定大小?

只是仔细检查一下,我已经在Google上搜索了一些和所有与我类似的代码,声称它们会导致存储大小错误。

甚至Deitel的C ++如何编程p。常见编程错误4.5下的261个状态:

仅常量可用于声明自动和静态数组的大小。

开导我


3
注意,DMA的意思是“直接内存访问” -我想你是问有关动态分配

3
C还是C ++?选择一个
Lightness Races in Orbit 2015年

1
再次选择一个:C或C ++。这个问题是明确的,仅关于C。不应有C ++标签。
基金莫妮卡的诉讼

Answers:


70

这在C99中有效。

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

请注意,这与malloc和有所不同newgcc就像int array[100]通过调整堆栈指针一样在堆栈上分配数组。没有堆分配完成。就像_alloca


13
我在几个月前编写的代码库中的文件中遇到了这种情况。我和团队的其他成员一样困惑于为什么要编译。在我们的情况下,在声明数组之前也要计算数组的大小(这也不应该吗?)无论如何,挑战就解决了。任何可以回答为什么这是合法的人都会受到欢迎。如果您曾经在西雅图,请告诉我。我有一个流行蛋pop。
杰夫·兰姆

2
在这种情况下,您能否提供一些有关堆栈内部工作方式的信息/链接?这会在运行时带来一些开销吗?
2011年

2
@balki开销很小,因为它基本上是增加/减少堆栈指针。如果将原始堆栈指针保存在函数的开头,则堆栈行为可以与正常情况基本相同。
mmx

这在c ++中允许吗?Visual Studio不允许这样做吗?
justpraveen

25

这就是所谓的VLA(可变长度数组)。它在c99中是标准的,但是gcc允许它在c ++代码中作为扩展。如果你想让它拒绝代码,尝试尝试-std=standard-ansi-pedantic选项。


2
-std-ansi选项对这个扩展都没有关系。
乔纳森·韦基利


4

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


2
我想它将在C ++ 0x中得到支持
mmx

不符合标准草案第8.3.4节的规定。

3
它永远不会包含在c ++ 1x:D中,但是我们希望dynarray <T>可以进入。我会喜欢的。所以你可以做dynarray <int> a(some_size); 并使其高效分配,可能使用诸如_alloca之类的编译器hax等。
Johannes Schaub-litb

3
对于将来的任何人:它将被包含在C ++ 14中(具有较小的功能集,如typedefsizeof()等)。
红色XIII

2
@RedXIII:不好猜。VLA也不dynarray是C ++ 14的一部分。
magras

1

该代码在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;
}

0

如果使用的是我尝试过的Dev-Cpp编译器,则可以动态地给数组提供大小,但是没有错误,但是在Visual C ++和Visual Studio编译器上是不可能的。我认为原因是dev-c ++为未初始化的int分配了一个正数,当我们给它一个数时,它会被给定的数替换。但是也许其他编译器将空值赋给未初始化的变量。


大多数编译器不会为未初始化的局部变量分配任何内容,它们通常看起来将保留它们所占用的内存中的任何内容,直到由程序分配它们为止。您所引用的Dev-C ++似乎是MinGW之上的IDE,其中包括GCC端口作为编译器。如其他答案所述,VLA不是标准的C ++,但是某些编译器(包括g ++)仍然支持它们。
杰里(Jerry)

Dev-C ++不是编译器。Visual Studio也不是。Dev-C ++使用GCC / G ++作为其编译器,而Visual Studio使用cl(Microsoft的编译器后端)。Dev-C ++和Visual Studio本身就是集成开发环境(IDE)。这是一个重要的区别。Dev-C ++不会“分配”任何东西。编译器会这样做。
Elkvis

0

我最近遇到了需要堆栈分配数组的情况。(这是v8的包装,每个方法调用都需要一个args数组)。

一个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个大小的数组,但这并不是那么好。)


-1

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


2
VLA仍然不是该标准的一部分。有一个dynarray TS,但至今尚未批准。
杰森
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.