Question

We all know the basic rules for static array:

int size = 20;
char myArray[size];

is not legal. And.

const int size = 20;
char myArray[size];

is OK.

But, what about this.

int f(const int size)
{
    char myArr[size];
}

void main()
{
   f(2);
   f(1024);
}

MSVC says it is an error, gcc seems to compile and execute it fine.

Obviously, it is not portable, but should it be accepted?

Which compiler does the right thing in that situation?

Also, if it is permited by the compiler, should it be permited by good programming standards/practice?

EDITED: The idea is that I would want stack allocation for the speed, but I would not know at compile time the size of the array. I know that there is some other solutions, and that stack alloc would probably not be a significative optimization, but I think it is an interesting usage.

Was it helpful?

Solution

No. C++ has no variable-length arrays. C99 does, and gcc allows it via extension.

Use a std::vector.


Assuming you have profiled your application and found this to be a bottleneck, write a custom allocator that allocates from the stack and use that. If not, there's not a problem.

Stack allocation is very fast, but this likely isn't going to be a main concern in a real application. (You should have a custom memory management scheme in place that will performance close in speed to stack allocation.)

OTHER TIPS

You can use std::array for this. std::array was added in the TR1 extensions and is available in the namespace std or std::tr1 depending on the compiler / standard library version you're using.

#incldue <array>
int main()
{
   std::tr1::array<int,25> myArray;
   //etc...
   myArray[2] = 42;
}

reread the question, regarding stack allocation...

If you want stack allocation, you can use alloca to allocate on the stack instead of malloc(all usual warnings apply).

If you want to a friendlier interface you can implement a custom stl allocator based on alloca and use a std::vector with this (you should read up before implementing).

e.g.:

#include <vector>
template <class T>
class MyStackAllocator
{ // implemented per std::allocator spec
...
}
int main()
{
//allocate a vector on the stack and reserve n items
vector<int, MyStackAllocator<T>> vecOnStack(25);
...
}

The variable length arrays (VLA) are supported by C99, but not by C++. gcc allows it through the extension.

std::vector is doing in C++ what VLA is doing in C99

Correct answer was actually supplied in this thread, so I just want to provide more context to it.

You need to create custom allocator which uses alloca() (or _alloca() in Windows) function for dynamic stack allocation. It's very easy to create one, you can use a typical allocator boilerplate, change allocate() member function to return (pointer)(alloca(size * sizeof(T))); and make deallocate() function empty, because there is no manual stack deallocation. After that you can supply your allocator to the standard containers, e.g. vector<T, stack_allocator<T>>.

There are two caveats, though. Allocate-able stack size can vary significantly, often you have an option to set it at compile time. Visual Studio in 32-bit applications I believe limits it to 1MB by default. Other compilers may have different limits. In 64-bit applications there isn't really any problems as stack can be as large as heap. You will probably need to catch structured exception on stack overrun and convert it to C++ exception.

The second caveat, you should never copy the stack pointers outside of your function, so move semantics, for example, will not work if you pass stack allocated objects to/from the function.

And there is also one inconvenience, you cannot copy containers with incompatible allocators, but you can copy them element by element. E.g.

vector<int> vint;
vector<int, static_allocator<int>> vsint;

vint = vsint; // won't compile, different allocators
std::copy(vsint.begin(), vsint.end(), vint.begin()); // fine

What you really want isn't quite what you've asked. It seems that you really want a map of numbers to numbers, such that index 2042 holds the value 23, etc.

Since you don't actually know the upper bound of the highest number you might want to use, you will probably have to restructure you code in such a way that it uses a (mathematical) map, where instead of considering 2042 the index of an array holding, you consider 2042 the key to access the value 23.

---- Answer to the can we allocate a static array with an execute time constant below ---

If you want an execute time static array, the best option is to declare the array using the alternative pointer syntax, and then initialize it in a non-static init() like function at the start of the program execution.

If you attempt to allocate the array prior to the execution of main(...) you run the risk of not knowing which static blocks of code are going to be called in what order. Sometimes that makes little difference; but, in your case it seems you need the number to be computed at run time, so the order of the modules becomes important.

By using a non-static method, you esentially guarantee that all the static code is exercised prior to allocating the array.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top