Can we create a static array with a size that is a run-time constant?

We all know the basic rules for a static array:

int size = 20; char myArray[size]; 

not legal. BUT.

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

OK.

But how about this.

 int f(const int size) { char myArr[size]; } void main() { f(2); f(1024); } 

MSVC says this is a bug, gcc seems to compile and execute it in order.

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

Which compiler does the right thing in this situation?

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

Editorial: The idea is that I would like stack distribution for speed, but I would not know at compile time the size of the array. I know that there are other solutions, and that stack allocation is probably not a meaningful optimization, but I think this is an interesting use.

+6
c ++ coding-style
source share
5 answers

Not. C ++ does not have variable length arrays. C99 does, and gcc resolves it through the extension.

Use std::vector .


Assuming you have profiled your application and found that it is a bottleneck, write a custom allocator that allocates from the stack and uses it. If not, no problem.

Stack distribution is very fast, but this is probably not the main problem in a real application. (You should have a custom memory management scheme that will quickly bring performance closer to stack distribution.)

+9
source share

You can use std :: array for this. std :: array is added to the TR1 extensions and is available in the std or std :: tr1 namespace depending on the version of the compiler / standard library used.

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

re-read the question about stack distribution ...

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

If you want to use a more user-friendly interface, you can implement your own stl distributor based on alloca and use std :: vector with this ( you should read it before implementation ).

eg:.

 #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); ... } 
+3
source share

Variable Length Arrays (VLAs) are supported by C99, but not C ++. gcc resolves it through the extension.

std :: vector does in C ++ what VLA does in C99

+1
source share

The correct answer was actually provided in this thread, so I just want to provide it with more context.

You need to create your own distributor that uses the alloca() function (or _alloca() on Windows) to dynamically allocate the stack. It is very easy to create it, you can use a typical template distributor scheme, change the allocate () function for the return (pointer)(alloca(size * sizeof(T))); function return (pointer)(alloca(size * sizeof(T))); and make the deallocate() function empty, because there is no manual stack release. After that, you can provide a dispenser to standard containers, for example. vector<T, stack_allocator<T>> .

However, there are two caveats. The allocated stack size can vary significantly, often you have the option to set it at compile time. Visual Studio in 32-bit applications, in my opinion, limits it to 1 MB by default. Other compilers may have different restrictions. There is no problem in 64-bit applications, since the stack can be the size of a heap. You will probably have to catch a structured exception when the stack overflows and convert it to a C ++ exception.

In the second caution, you should never copy stack pointers outside of your function, so moving semantics, for example, will not work if you pass the stack to selected objects in / out of the function.

And there is also one inconvenience, you cannot copy containers with incompatible dispensers, but you can copy them by elements. For example.

 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 
+1
source share

What you really want is not exactly what you requested. It seems that you really need a map of numbers for numbers, so that index 2042 has a value of 23, etc.

Since you actually don't know the upper bound of the highest number that you might want to use, you will probably have to rebuild the code so that it uses a (mathematical) map, where instead of looking at 2042, the array index, you count the key 2042 to access the value 23.

---- The answer to the question: can we put a static array with a run-time constant below ---

If you need a static runtime array, the best option is to declare the array using alternative pointer syntax and then initialize it in non-static init() as a function at the beginning of program execution.

If you try to allocate an array before main(...) executed, you run the risk of not knowing which static blocks of code will be called in which order. Sometimes this is not much different; but, in your case, it seems you need the number to be computed at runtime, so the order of the modules becomes important.

Using the non-static method, you guarantee that all static codes are executed before the array is allocated.

0
source share

All Articles