2

The below code snippet works and compiles in C:

const int n=10;

int main(void)
{
    int a[n];
    return 0;
}

However, when the array is declared in global scope, it throws a compilation error.

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

int main(void)
{
    return 0;
}

Why doesn't it throw an error inside main?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Saurabh Sharma
  • 154
  • 1
  • 8

1 Answers1

5

Despite n being marked as const, it's not a compile time constant1. As such the array a is a variable length array2.

VLA's cannot have static storage duration. Placing it at file scope makes it a static variable, and your program is ill-formed because of it3.


  1. C11 N1570/6.6p6

    An integer constant expression117) shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, _Alignof expressions, and floating constants that are the immediate operands of casts. Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to the sizeof or _Alignof operator.

  2. C11 N1570/6.7.6.2p4

    If the size is not present, the array type is an incomplete type. If the size is * instead of being an expression, the array type is a variable length array type of unspecified size, which can only be used in declarations or type names with function prototype scope;143) such arrays are nonetheless complete types. If the size is an integer constant expression and the element type has a known constant size, the array type is not a variable length array type; otherwise, the array type is a variable length array type.

  3. C11 N1570/6.7.6.2p2

    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.

Community
  • 1
  • 1
StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • I think, it should be noted that VLA's do not need to be allocated on the stack, they can be allocated on the heap as well: `int (*array)[foo] = malloc(sizeof(*array));`. The restriction is an explicit restriction to deal with the fact that there is no defined execution order of global/thread storage declaration statements in C. Consequently, there is no notion of "this variable has that value at this VLA declaring statement" for globals. – cmaster - reinstate monica Mar 20 '17 at 07:49
  • @cmaster - The C standard makes no mention of stack or heap, and nor did I. I was very careful to stick with the wording of the standard, that speaks in terms of storage duration. – StoryTeller - Unslander Monica Mar 20 '17 at 07:50
  • @cmaster that is a (dynamically) allocated array being pointed to by a pointer of variably modified type. The term "VLA" refers to automatic arrays – M.M Mar 20 '17 at 07:53
  • @M.M That is a very narrow interpretation of the term "VLA". Afaik, the C standard does not primarily talk about VLAs in that narrow sense (apart from specific exemptions like the ones cited in this answer), rather it defines what a "variable length array type" is, and allows them to be used pretty much anywhere in executable code. Your specific meaning of VLA is just a specific consequence of a much broader concept. – cmaster - reinstate monica Mar 20 '17 at 10:08
  • To put it another way, you could say that all malloc'd space is arrays with runtime length. – M.M Mar 20 '17 at 10:23