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

8

84

I've been using C++ for a few years, and today I saw some code, but how can this be perfectly legal?

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;
}

Compiled under GCC.

How can the size be determined at run-time without new or malloc?

Just to double check, I've googled some and all similar codes to mine are claimed to give storage size error.

Even Deitel's C++ How To Program p. 261 states under Common Programming Error 4.5:

Only constants can be used to declare the size of automatic and static arrays.

Enlight me.

Mountain answered 10/4, 2009 at 10:21 Comment(4)
note that DMA means "direct memory access" - I think you are asking about dynamic allocationStanhope
C or C++? Pick one.Dagon
Again, pick one: C or C++. This question is explicitly and only about C; there should not be a C++ tag.Stanhope
See also Why aren't variable-length arrays part of the C++ standard?Eran
C
75

This is valid in C99.

C99 standard supports variable sized arrays on the stack. Probably your compiler has chosen to support this construct too.

Note that this is different from malloc and new. gcc allocates the array on the stack, just like it does with int array[100] by just adjusting the stack pointer. No heap allocation is done. It's pretty much like _alloca.

Clifton answered 10/4, 2009 at 10:22 Comment(5)
I came across this same scenario in a file in our code base that was written months ago. I was baffled, as was the rest of the team, as to why it compiled. In our situation, the size of the array was calculated before declaring the array as well (which shouldn't be allowed, either?) Anyway, a challenge went out. Anyone who could answer why this is legal gets a pop tart. If you're ever in Seattle, let me know. I have a pop tart for you.Fideism
Can you provide some info/link on how stack internally works in this case? Does this introduce some overhead in run time?Oversupply
@Oversupply The overhead is minor, as it's basically increment/decrementing the stack pointer. The stack behavior can be essentially identical to the normal case if you save the original stack pointer at the beginning of the function.Clifton
is this allowed in c++ ? Visual studio does not allow this?Linden
What I don't get is that when assembler generates the assembly code, it does not know the exact size of array at that time. So how much offset it is going to move the stack pointer to make room for this dynamic-sized array? It can't tell. So it is pretty interesting to know how this is implementedAccordingly
D
27

This is known as VLAs (variable length arrays). It is standard in c99, but gcc allows it in c++ code as an extension. If you want it to reject the code, try experimenting with -std=standard, -ansi and -pedantic options.

Destiny answered 10/4, 2009 at 11:0 Comment(1)
The -std and -ansi options have no bearing on this extension at all.Richers
A
7

It is valid only in C99. Next time you may try checking your code in a reliable compiler.

Athalia answered 10/4, 2009 at 10:29 Comment(0)
S
6

It is valid C99, it is not valid C++. This is one of not a few differences between the two languages.

Stanhope answered 10/4, 2009 at 10:33 Comment(6)
I guess it's going to be supported in C++0xClifton
Not according to section 8.3.4 of the draft standard.Stanhope
it won't ever be included in c++1x :D but let's hope dynarray<T> gets in. i would love it. so you could do dynarray<int> a(some_size); and have it allocate efficiently, possibly with compiler hax like _alloca and so on.Leatri
For anyone from the future: it will be included in C++14 (with smaller set of features such as typedef, sizeof(), etc.).Stead
@RedXIII: Bad guess. Neither VLA nor dynarray are parts of C++14.Soviet
@JohannesSchaub-litb Are there plans to introduce it in further realeases of the Standard?Mono
N
2

This Code runs in GNU GCC Compiler.

#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;
}
Nieberg answered 3/9, 2015 at 19:37 Comment(0)
P
1

You can give size to an array dynamically in if you are using Dev-Cpp compiler I have tried it and got no error but on visual c++ and visual studio compilers it is not possible. I think the reason is that dev-c++ assigns a positive number to the uninitialized int and when we give it a number it is replaced by the given one. but perhaps other compilers give null to uninitialized variables.

Priestly answered 5/3, 2013 at 7:5 Comment(2)
Most compilers don't assign anything to uninitialized local variables, they will usually appear to hold whatever was in the memory that they occupy until they are assigned by the program. It seems the Dev-C++ you referenced is an IDE on top of MinGW, which includes a port of GCC as the compiler. As noted in other answers, VLAs are not standard C++, but some compilers (including g++) support them anyway.Olsson
Dev-C++ is not a compiler. Neither is Visual Studio. Dev-C++ uses GCC/G++ as its compiler, while Visual Studio uses cl (Microsoft's compiler back-end). By themselves, Dev-C++ and Visual Studio are Integrated Development Environments (IDEs). This is an important distinction to make. Dev-C++ does not "assign" anything. The compiler does that.Jandy
C
1

I recently came across a scenario where a stack-allocated array is desired. (It's a wrapper around v8, needed an array of args on every method call).

An std::vector would do heap memory allocation, whose performance is not acceptable.

Here is my solution, use template to allocation array of cases:

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
   }
}

(And of course, I can just do with a 32-sized array, but which is not so elegant.)

Coleoptile answered 21/10, 2019 at 8:27 Comment(0)
J
0

Variable Length Arrays (VLAs) are supported in the C++14 standard, which has recently been accepted, and is awaiting publication.

Jandy answered 13/10, 2014 at 14:38 Comment(1)
VLAs are still not part of the standard. There's a dynarray TS, but as of yet it isn't ratified.Jegger

© 2022 - 2024 — McMap. All rights reserved.