5

I'm aware that if you set a dynamic value in c/c++ you can't use that value within brackets to allocate an array (which would make it a so-called variable length array (VLA), which the current C++ standard does not support)...

i.e. See:
C++ : Variable Length Array
http://en.wikipedia.org/wiki/Variable-length_array

What I don't quite get (and what I haven't see asked precisely here) is why GNU c/c++ compilers (gcc, g++) are okay with using dynamic allocation based on an integer value (as far as I can tell) so long as that value is a constant within the scope of the array allocation, but Visual Studio's does not support this and will refuse to compile the code, spitting out errors.

e.g. in g++

void Foo(const unsigned int bar) { double myStuff[bar]; //... do stuff... } 

...compiles just fine...

But the same code refuses to compile in versions of VS I've used, unless whatever I pass to bar is const in all scopes or is a #define, static const, etc.

I would suspect that maybe GNU compilers use the scope to infer that this value is a constant within that scope and either simply assign it to a malloc or handle it specially somehow.

My questions are:

  1. Who (VS or GNU) is closer to the standard in terms of how they handle this?
  2. Is there a way to do this VS using [] on a value that's constant within scope, but not globally const throughout the entire program without a malloc call?
  3. Are there any issues I should be aware of if I use this in my GNU-compiled code?
6
  • 2
    If it's not C99 it's not guaranteed to work so anything goes. Commented Nov 15, 2013 at 21:18
  • 2
    You should choose a language. This is valid C (since 1999), but not yet valid C++ (but probably will be from 2014). GCC supports it as a non-standard extension to C++; other compilers may not. Commented Nov 15, 2013 at 21:25
  • Where I got hung up was that all the examples I saw relating to the language spec involved VLAs that were declared with values that were non-const w/in the scope of the declaration, as I say below. By contrast bar is const within the scope but was not known at compile time. I guess g++ supports allocation via both non-const and const vars within the current scope (according to a quick test I did). And I know either way the array is dynamic. That said I was unsure whether the const case was considered a VLA in spec terms, as the lack of examples of this flavor might hint @.... Commented Nov 15, 2013 at 21:29
  • Short version: I was was unsure if VLA in spec terms was ALL dynamic-length arrays (e.g. all arrays not declared by a value that is not a literal at compile time) or just arrays that were declared via a length variable that was non-const within the declaration scope (which would make the VLAs in spec-terms a specific subset of dynamic arrays). Commented Nov 15, 2013 at 21:33
  • @MikeSeymour - at the Chicago meeting N3639, "Runtime-sized arrays with automatic storage duration", was not approved for C++14; instead, it will go into a separate TS, along with N3662, "C++ Dynamic Arrays (dynarray)". Commented Nov 15, 2013 at 21:54

2 Answers 2

5

From a language point of view, VLAs are only supported in C, and only from C99 on. They are not supported in C++.

From a compiler point of view, g++ will support VLAs as extensions to C90 and C++, but if you compile with -pedantic it will disable those extensions and you'll get a compile error.

Visual Studio does not support VLAs at all in either C or C++. VS only supports up to the C89 standard, and AFAIK MS has no plans to support the later C standards at all.

As far as scope is concerned, that's defined in the C standard:

6.7.6.2 Array declarators
...
2 If an identifier is declared as having a variably modified type, it shall be an ordinary identifier (as defined in 6.2.3), have no linkage, and have either block scope or function prototype scope. If an identifier is declared to be an object with static or thread storage duration, it shall not have a variable length array type.

There are technical reasons why VLAs cannot be declared static or at file scope; objects with static storage duration are allocated at program startup and held until the program terminates, and if I'm not mistaken it's not guaranteed that objects will be allocated and initialized in any particular order. So those items need to have their size known at compile time.

Sign up to request clarification or add additional context in comments.

4 Comments

Ah so that means the above example is okay, but if I changed const unsigned int bar to unsigned int bar in the above snippet, it wouldn't satisfy C99, as my commentary suggests? If so why is that? Is it due to the compiler being able to insert code at the scope entry level to resize the stack based on stack variables in preparation for possible declaration of arrays within a scope? (That's the first reason why that came to mind.)
@JasonR.Mick: Whether or not the expression used as the size of the array is const is irrelevant. What John Bode is saying is that the variable-length array itself cannot be static or thread-local. That has nothing to do with const-ness.
@JasonR.Mick In C, and consequently in gcc's C++ dialect, bar does not need to be constant. Neither are you required not to change the value of bar after declaring the array. The array, however, will retain the size it had when it was defined. The C standard actually specifies that you can typedef an array type using a runtime value for an array dimension, which will behave as if you had an implicit constant initialized for the array size at the point of the typedef. This is a very little known part of the C language, though...
@rici Yup, I get that, I was just explaining what I was trying to ascertain. Exactly what you said. :)
3

the GNU compiler collection has supported Variable Length Arrays as an extension, compile with -pedantic and you'll see the expected warning.

#include <iostream> int main() { int foo = 10; int bar[foo]; } 

compile:

g++-4.8 -std=c++11 -O2 -pedantic -pthread main.cpp && ./a.out main.cpp: In function ‘int main()’: main.cpp:6:16: warning: ISO C++ forbids variable length array ‘bar’ [-Wvla] int bar[foo]; ^ 

3 Comments

Ahhh, that makes sense. So are there any downsides/shortcomings in GNU that I should beware of? I appreciate you give a clear, full-fledged answer here as again the examples I saw elsewhere on VLAs all dealt with locally declared or function parameter values that were non-const within the scope, hence it was somewhat confusing whether that was viewed as a "VLA" or not, i.e. whether VLA refers to all arrays allocated via dynamic lengths, or a special subset that are allocated by values that are non-const within a scope (hence the use of only non-const examples).
@JasonR.Mick: An array is a VLA even if the parameter is const in scope because it might be called from multiple locations with different parameters. The stack has to be resized in the same dynamic way instead of using constant values.
Oh I get that, I just was wondering if const might be allowed or specially handled as if the compiler looks ahead and sees a const level value used, it could insert code to at runtime (note: not compile time) adjust the length of the stack upon entering the scope of declaration, versus for a non-const value you would have to wait until the instant it was allocated to resize the stack. The latter seems a safer method as you could pre-size the stack sooner, doing that upon entering scope (e.g. making the function call).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.