4

If I write variable length array as a locally, like this:

#include <stdio.h>

int main()
{
    int i=1;
    int a[i];
    printf("%zu",sizeof(a));
}

It working fine in GCC compiler.

But, If I write Variable length array as a globally, like this:

#include <stdio.h>
int i=1;
int a[i];
int main()
{
    printf("%zu",sizeof(a));
}

Then, GCC compiler gives following an error:

prog.c:4:5: error: variably modified 'a' at file scope
  int a[i];
msc
  • 33,420
  • 29
  • 119
  • 214
  • If the array is declared with a constant '1' the compiler should declare the array of size 1, I haven't tried it buts that's what I'm thinking. – SPlatten Dec 14 '17 at 08:58
  • @SPlatten - In C++. In C a `const int` is not a constant expression. – StoryTeller - Unslander Monica Dec 14 '17 at 09:03
  • I found a way to declare a variable length array globally, this is not straightforward but doable. See my aswer there https://stackoverflow.com/questions/10360394/declaring-a-variable-length-array-as-a-global-variable-in-c/56924075#56924075 – Phi Jul 08 '19 at 13:19

4 Answers4

15

From standard 6.7.6.2

If an identifier is declared to be an object with static or thread storage duration, it shall not have a variable length array type.

user2736738
  • 30,591
  • 5
  • 42
  • 56
6

It's not allowed because unless it is restricted to the extreme, it could be exceptionally error prone. Consider this:

extern const int sz; // Another TU
int a[sz];

The size of the array depends on the initialization order between it and sz (which in our example is in another transnational unit). It could produce a 0 sized array (ill-formed). The correctness of programs being built should not depend on such things.

So if we limit its size to variables in the current TU only, we end up with:

const int sz = 10;
int a[sz];

But why use a VLA at all in this case? Just specify the size with the constant expression 10.

It's just not a useful feature. Not to mention, as @M.M pointed out, that it goes against the design goal of easily allowing static data to be pre-built into the binary.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • 3
    Also the static initialization restrictions are designed to allow for the static data area to be preconstructed and built into the binary ; OP suggestion is incompatible with this – M.M Dec 14 '17 at 09:12
  • @M.M - Excellent point. I nabbed it into the post. – StoryTeller - Unslander Monica Dec 14 '17 at 09:14
  • What about creating a static `int` array inside a function using the length of a compile-time known array of strings? The compiler knows how long the array is, it can be passed as a `const`, and so it isn't variable-length. Yet it refuses to compile with a bogus error. C _should_ allow `const` sizes for fixed-length arrays, but it doesn't by pretending they are variable-length, thus copping out. – SO_fix_the_vote_sorting_bug Jan 05 '23 at 03:51
5

You already have the answer, but just to elaborate on why part, let me add my two cents.

First, about lifetime: (quoting C11, chapter §6.2.4/P2)

The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it. An object exists, has a constant address,33) and retains its last-stored value throughout its lifetime.34)

Then, static storage duration: (quoting P3)

An object whose identifier is declared without the storage-class specifier _Thread_local, and either with external or internal linkage or with the storage-class specifier static, has static storage duration. Its lifetime is the entire execution of the program and its stored value is initialized only once, prior to program startup.

and , the linkage: (chapter §6.2.3/P5)

[...] If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external.

So, in this case, a is to have static storage duration.

Now, by definition, VLA dimension is acquired at runtime, so there's noway compiler can know and allocate memory/storage and initialize it at the beginning (prior to program startup, as required for static storage duration), hence this is a conflict.

As mentioned in C11 chapter 6.7.6.2, standard explicitly forbids this.

[...] If an identifier is declared to be an object with static or thread storage duration, it shall not have a variable length array type.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
5

Because the standard says so. But that isn't very helpful; the reason why this isn't allowed by the standard, is that all file scope variables must be initialized before main() is called. This in turn means that they must consist of compile-time constants only.

The purpose of a VLA is to grab the size in run-time. We can't have an array where the size is determined both at compile-time and run-time. If you have need for a variable size array at file scope, use a pointer and then in run-time have it point to an allocated array, such as for example an array allocated with malloc().

Lundin
  • 195,001
  • 40
  • 254
  • 396