Why doesn't work Variable length array as a globally? [duplicate]

谁都会走 提交于 2019-12-19 09:16:16

问题


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];

回答1:


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.




回答2:


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().




回答3:


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.




回答4:


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.



来源:https://stackoverflow.com/questions/47809299/why-doesnt-work-variable-length-array-as-a-globally

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!