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?
Community
  • 1
  • 1
Jason R. Mick
  • 5,177
  • 4
  • 40
  • 69
  • 2
    If it's not C99 it's not guaranteed to work so anything goes. – Jesus Ramos Nov 15 '13 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. – Mike Seymour Nov 15 '13 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 @.... – Jason R. Mick Nov 15 '13 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). – Jason R. Mick Nov 15 '13 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)". – Pete Becker Nov 15 '13 at 21:54
  • +1 visual studio did [not support c99 until recently](http://stackoverflow.com/questions/18521398/which-c-compiler-should-i-trust/18521417#18521417) and apparently still does not support VLA `gcc` and `clang` to keep up with `gcc` support VLA as a extension outside of C99 mode i.e. in C++. – Shafik Yaghmour Nov 15 '13 at 22:06

2 Answers2

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.

John Bode
  • 119,563
  • 19
  • 122
  • 198
  • 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.) – Jason R. Mick Nov 15 '13 at 21:43
  • @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. – rici Nov 15 '13 at 22:00
  • @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... – cmaster - reinstate monica Nov 15 '13 at 22:02
  • @rici Yup, I get that, I was just explaining what I was trying to ascertain. Exactly what you said. :) – Jason R. Mick Nov 16 '13 at 01:10
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];
                ^
Sam Miller
  • 23,808
  • 4
  • 67
  • 87
  • 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). – Jason R. Mick Nov 15 '13 at 21:22
  • 1
    @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. – Zan Lynx Nov 15 '13 at 21:32
  • 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). – Jason R. Mick Nov 15 '13 at 21:38