14

I have some concepts about the VLA and its behavior that I need to clarify.

AFIK since C99 it's possible to declare VLA into local scopes:

int main(int argc, char **argv)
{
    // function 'main' scope
    int size = 100;
    int array[size];
    return 0;
}

But it is forbidden in global scopes:

const int global_size = 100;
int global_array[global_size]; // forbidden in C99, allowed in C++

int main(int argc, char **argv)
{
    int local_size = 100;
    int local_array[local_size];
    return 0;
}

The code above declares a VLA in C99 because the const modifier doesn't create a compile-time value. In C++ global_size is a compile-time value so, global_array doesn't become a VLA.

What I need to know is: Is my reasoning correct? Is the behaviour that I've described correct?

I also want to know: Why are the VLA not allowed in global scope? are they forbidden both in C and C++? Why is the behavior of arrays into global and local scope different?

PaperBirdMaster
  • 12,806
  • 9
  • 48
  • 94
  • 6
    Let's suppose global VLAs are allowed. When is their (variable) size actually defined ? – cnicutar Dec 28 '12 at 20:17
  • 1
    @cnicutar well... like all the VLA, in execution time, like the other scopes. I know that this isn't the answer, but I want to know WHY. – PaperBirdMaster Dec 28 '12 at 20:19
  • 1
    http://stackoverflow.com/a/5052083/174605 – coelhudo Dec 28 '12 at 20:20
  • 3
    Yes, so a global VLA, how would you know when the value is defined? To make it meaningful, it requires that you can set the value of the size before the array is built - and the size needs to be known at compile time to tell the system how much space the OS needs to give the executable when it gets loaded. – Mats Petersson Dec 28 '12 at 20:23
  • cnicutar's question , particularly the word *variable* is *not* trivially answerable, and should not be viewed as such. As the link posted by coelhudo discuses, C and C++ have decidedly different ideas of what a const variable is. Ultimately, however, VLAs require stack space for allocation, something a global variable does not have. – WhozCraig Dec 28 '12 at 20:31
  • 1
    @coelhudo I know the difference of `const` between C and C++, as I commented on my question; only I want to know if my reasonings were true. – PaperBirdMaster Dec 28 '12 at 20:37
  • No such thing as VLA in C++. – Martin York Dec 28 '12 at 22:31
  • 3
    Voting to reopen as this is NOT a duplicate of the linked "duplicate". The linked question asks how to avoid the error that VLAs are not permitted at file scope; this question asks *why* VLAs are not permitted at file scope. – M.M Sep 30 '14 at 04:22
  • To me, at scope level, VLA-type allocation makes sense in a lock-free context (i.e. not only for "optim") when the size can't be determined at compile time. I only see (thread-specific) heap preallocation as an alternative to that, which is overkill most of the time, error prone and unreadable; do you know any other alternative? – moala Feb 10 '17 at 09:44
  • @JensGustedt if your reopening was justified, please remove the link to the duplicate, otherwise please re-close the Question. – Cœur Jul 08 '18 at 16:19

5 Answers5

15

Yes your reasoning is correct, that is how these different forms of array declarations and definitions are viewed by C and C++.

As others already stated, VLA with a veritable variable length (non-const) in global scope is difficult to make sense. What would the evaluation order be, e.g if the the length expression would refer to an object of a different compilation unit? C++ doesn't have VLA, but it has dynamic initialization of objects at file scope. And already this gives you quite a head ache, if you have to rely on evaluation order.

This leaves the small gap for C concerning length expressions that contain a const qualified object, which isn't allowed. This comes from the fact that such objects are not considered "integer constant expressions" by the C standard. This could perhaps change in future versions, but up to now the C committee didn't find it necessary to allow for such a thing: there are enum constants that play that role in C. Their only limitation is that they are limited to int in C, it would be nice to also have them size_t.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
  • 2
    Finally someone proves to have read the whole question! (+1 for this) IMHO this question isn't [duplicate](http://stackoverflow.com/questions/1712592/variably-modified-array-at-file-scope) because I'm focusing in other facts. Thanks for the explanation and thanks for answering almost all my questions. – PaperBirdMaster Dec 29 '12 at 13:08
  • I’m not a C person, but looking over the [C23 proposed features table](https://en.cppreference.com/w/c/23), it seems that [N3008](https://open-std.org/JTC1/SC22/WG14/www/docs/n3008.htm) adds `constexpr` to C. It does not explicitly say that a `constexpr` variable in an array bound is an “integer constant expression”, maybe that follows from what is in N3008 and the current C standard. – Quirin F. Schroll Oct 05 '22 at 12:50
  • 1
    @Bolpat Indeed, things are going to change here with C23. As you say there are `constexpr` that allow to define constant expressions of almost arbitrary type (and yes these are suitable for array bounds if they have integer type) and there are also generalizations for enumerations that allow to have other types then just `int` for the constants. – Jens Gustedt Oct 06 '22 at 13:14
4

I think the fundamental reason is a global variable has linkage, its size has to be known at compile time. If not, how could one link the program?

local variables have no linkage and the VLAs are allocated on the stack, which grows dynamically as the program runs.

4

C++ doesn't support VLAs, period. The reason the second code snippet works in C++ is that the const keyword creates a compile-time constant in C++; in C, it doesn't.

C99 doesn't support VLAs outside of block scope, period, regardless of how you declare the size variable. Note that C2011 makes VLA support optional.

John Bode
  • 119,563
  • 19
  • 122
  • 198
  • 1
    Yes, I know that `const` keyword creates a compile-time constant in C++ and in C it doesn't, I've commented this on the question. – PaperBirdMaster Dec 28 '12 at 20:38
3

There is a difference between being forbidden and not being allowed. ;-)

The VLA feature is designed to allow the use of stack space for a local array, to avoid the use of malloc for heap allocation. It is mostly a speed optimization.

Now you want to use VLAs outside of functions. Why? There is not much to win speedwise in avoiding a single malloc call during program start. And what stack space are we supposed to use for variables with a static life time?

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
1

So, for global VLA's, one of the issues (there are many variants on the theme) can be shown here:

int size;
int a;
int v[size];
int b;

.... in another file:

extern int a;
extern int b;

The linker will have to know where a and be are in relation to each other at link time, or it won't be able to fix them up correctly at load-time.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227