<p>At first C did not have variable-length arrays; all array sizes must be compile times constants. Then, in C99, variable-length arrays, a controversial addition, were added, permitting runtime-sized stack arrays.</p>
<pre class="lang-c prettyprint-override"><code>int x;
scanf(&quot;%d&quot;, x);
int vla[x];
</code></pre>
<p>The addition had implications such as <code>sizeof()</code> being able to evaluate arguments at runtime. But is this implication avoidable? Why are variable-length arrays such a controversial feature? What are the implications and catches of implementing variable-length arrays, and how do compilers usually get around them or avoid them?</p>

<c><arrays><stack>
What are the implications of implementing variable-length arrays?
CC BY-SA 4.0
2023-06-12T10:54:58.850Z
Ooh, our first bounty is on this question
Starship
<p>I recall this feature being a GNU extension for a long time before becoming standardized. I suspect it was implemented using <code>alloca()</code> or similar to allocate space on the stack.</p>
<p>This is certainly born out by the <a href="https://en.wikipedia.org/wiki/Variable-length_array" rel="nofollow noreferrer">Wikipedia page on the subject</a>.</p>
<p>There is a very good quality answer to this question <a href="https://stackoverflow.com/q/1887097">here</a>.</p>
<p>It's easily missed as its asked in the context of C++.</p>
<p>The big danger is the simple and obvious implementation is dangerous.
For example:</p>
<pre><code>foo(int n)
{
   int someArrayOnTheStack[n];
   // do stuff
}
</code></pre>
<p>You can easily overflow the stack if n is big. In our security conscious world that's a buffer overflow exploit waiting to happen.</p>
<p>You can get around that by allocating on the heap instead but that defies users expectations as it looks like a stack declaration but magically becomes a heap one with no visible call to <code>malloc()</code>.</p>
<p>Of course in C++ you'd just write:</p>
<pre><code>foo(int n)
{
   std::vector&lt;int&gt; someArray(n);
   // do stuff
}
</code></pre>
<p>Which matches expectations and so the feature is unnecessary there.</p>
<p>The linked Q&amp;A points out some other issues.</p>

CC BY-SA 4.0
2023-06-13T01:30:52.620Z
2023-06-13T01:32:07.330Z
2023-06-13T01:32:07.330Z
Bruce Adams
<p>VLAs were added to C99, but made optional in C11. The reason they were made optional <a href="https://softwareengineering.stackexchange.com/questions/314838/why-were-variable-length-arrays-made-optional-in-c-2011">doesn't appear to be in public documents</a>.</p>
<p>The initial proposal to add VLA to C (<a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n637.ps" rel="noreferrer">N637</a>) cited numerical computing as the motivation, and the proposal was based on an existing implementation on <a href="https://en.wikipedia.org/wiki/Cray" rel="noreferrer">Cray</a> platforms. In terms of burden on implementers, a similar feature existed on many platforms via the function <a href="https://man7.org/linux/man-pages/man3/alloca.3.html" rel="noreferrer"><code>alloca</code></a>, which is easy to implement on most platforms where the local variables of a function are on a <a href="https://en.wikipedia.org/wiki/Stack-based_memory_allocation" rel="noreferrer">stack</a> that's a contiguous block of memory (which is the case on almost all platforms). Nonetheless, at least one major C implementation cited VLA as a low-priority feature: in Visual C++, <a href="https://social.msdn.microsoft.com/Forums/en-US/6099f453-db2c-49c3-b59a-b799c379cebb/c99-variable-length-array-is-unsupported-and-give-bad-error-message?forum=vcprerelease#3b6b14b0-e9f0-47b2-abb1-79d46c004212-isAnswer" rel="noreferrer">they were one of the last missing C99 features</a> and <a href="https://devblogs.microsoft.com/cppblog/c11-and-c17-standard-support-arriving-in-msvc/#variable-length-arrays" rel="noreferrer">they will not be added</a>.</p>
<p>I think (but I don't have insider information) that the difficulties with VLA aren't in implementations, but for users. <a href="https://stackoverflow.com/questions/1018853/why-is-the-use-of-alloca-not-considered-good-practice">VLAs are bug-prone for many reasons</a>. An obvious one is that they can very easily lead to a stack overflow, which often has disastrous consequences (at best a crash, often memory corruption). Another consequence is that innocuous-looking constructs such as <code>sizeof(...)</code> may now have side effects, and even a simple <code>sizeof(a)</code> doesn't actually return the size of the array <code>a</code> if it's a VLA function parameter (that's true if it's a function parameter as well with a static size, but VLAs make it look more like it should work).</p>
<p>Another reason against having VLA in the C standard is that <a href="https://groups.google.com/g/comp.std.c/c/AoB6LFHcd88/m/BvA4NiBe2mcJ" rel="noreferrer">according to John Nagle on comp.std.c</a>,</p>
<blockquote>
<p>Prototypes of functions with VLA parameters do not have to exactly match the function definition. This is incompatible with C++ style linkage and C++ function
overloading, preventing the extension of this feature into C++.</p>
</blockquote>
<p>C++ is mostly an extension of C; it tweaks some behavior (enough that most idiomatic C programs aren't valid C++) but having a major feature of C that's not in the next edition of C++ is unusual, and is problematic for compilers that handle both languages (which is most C++ compilers).</p>
<p>From personal experience in as a C programmer on embedded platforms, we never use VLAs, even when we're sure that all compilers we care about would support them. They're too bug-prone and they make it impossible to predict your program's stack size (we like to make sure that the deepest nesting of function calls will not overflow the stack — we don't use recursion either). <a href="https://groups.google.com/g/comp.std.c/c/AoB6LFHcd88/m/V-3kJfQ3VYgJ" rel="noreferrer">Jens Gustedt on comp.std.c</a> also cites GPUs as a type of platforms where VLAs aren't welcome (I don't know exactly why, but I guess because the memory assigned to each thread's stack tends to be limited).</p>

CC BY-SA 4.0
2023-06-16T18:47:44.177Z
2023-06-17T20:11:01.217Z
2023-06-17T20:11:01.217Z
Gilles 'SO- stop being evil'
CC BY-SA 4.0
2023-06-16T19:22:48.027Z
"in Visual C++, they were one of the last C99 features to be added." -- It's my understanding that it _still_ doesn't fully implement C99, if nothing else because it doesn't understand the `restrict` keyword (you have to write `__restrict` instead).
Bbrk24
CC BY-SA 4.0
2023-06-16T20:21:17.840Z
@Bbrk24 In fact VS doesn't implement VLAs at all (I realize what I wrote is a bit misleading). They never really tried to implement C99 and went directly to C11.
Gilles 'SO- stop being evil'
CC BY-SA 4.0
2023-12-13T23:15:33.703Z
No version of the C Standard has ever specified as a condition of conformance that an automatic-duration object definition of the form `int arr[n]` behave meaningfully for any particular value of `n`, nor specified what should happen if `n` exceeds the maximum value an implementation can handle.  The only real effect of making the feature optional is that implementations that wouldn't otherwise support VLAs of non-trivial size needn't waste effort pretending to support them, and can instead reject at compile time programs that would be unlikely to behave usefully at run time.
supercat
<p>I'd say one of the reasons is that it was a rather niche feature with a very natural syntax (which you usually try to avoid). Most times I've seen VLAs used in code, it was by novice programmers who didn't care much about how it worked and just preferred it to the more verbose heap allocations. Another common case is people intending to encapsulate the array size in a compile-time variable, but forgetting(/not realizing the need) to mark it as <code>constexpr</code> or at least <code>const</code>. There's little benefit to a feature like this, and it introduces confusion to users and complexity to the language (like, as you've mentioned, having <code>sizeof</code> operate at runtime in some cases). It's a much more fitting solution to provide the <code>alloca</code> function as the API for stack allocations for cases when it is actually needed, and have the programmers handle the resulting variable-length array by pointer, same as in other cases.</p>
<p>As for whether the implications can be avoided, I'd say, possibly, but not in the general case. If, for instance, the base-pointer optimization is enabled (making the local variables be resolved through the stack pointer instead of the base pointer), any VLA significantly slows down the local variable access (as it needs to perform at least one more operation every time). Overall, perhaps some clever tricks could be introduced, but VLAs seem to be of too little use to overcome such difficulties for.</p>
<p>Also worth noting is that a similar concept of variable-sized structs (i.e. having an array extend past the end of a struct) is a widely used idiom in C/C++, despite having almost no specific language support (like no special cases for <code>sizeof</code> nor automatic copying).</p>
<p><strong>TL;DR</strong>: <code>alloca</code> does the trick just as well, but is less confusing both for users and language designers</p>

CC BY-SA 4.0
2023-06-11T23:32:41.813Z
2023-06-11T23:32:41.813Z
abel1502
# What are the implications of implementing variable-length arrays?
Posted by: username_0 on 2023-06-09
At first C did not have variable-length arrays; all array sizes must be compile times constants. Then, in C99, variable-length arrays, a controversial addition, were added, permitting runtime-sized stack arrays.
int x;
scanf("%d", x);
int vla[x];

The addition had implications such as sizeof() being able to evaluate arguments at runtime. But is this implication avoidable? Why are variable-length arrays such a controversial feature? What are the implications and catches of implementing variable-length arrays, and how do compilers usually get around them or avoid them?
**Tags:** c arrays stack
> **Comments:**
> **username_1**: Ooh, our first bounty is on this question  
---
## 3 answers
### Answer by username_3 on 2023-06-16. Score: 9 | Accepted answer
VLAs were added to C99, but made optional in C11. The reason they were made optional [doesn't appear to be in public documents](https://softwareengineering.stackexchange.com/questions/314838/why-were-variable-length-arrays-made-optional-in-c-2011).

The initial proposal to add VLA to C ([N637](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n637.ps)) cited numerical computing as the motivation, and the proposal was based on an existing implementation on [Cray](https://en.wikipedia.org/wiki/Cray) platforms. In terms of burden on implementers, a similar feature existed on many platforms via the function [`alloca`](https://man7.org/linux/man-pages/man3/alloca.3.html), which is easy to implement on most platforms where the local variables of a function are on a [stack](https://en.wikipedia.org/wiki/Stack-based_memory_allocation) that's a contiguous block of memory (which is the case on almost all platforms). Nonetheless, at least one major C implementation cited VLA as a low-priority feature: in Visual C++, [they were one of the last missing C99 features](https://social.msdn.microsoft.com/Forums/en-US/6099f453-db2c-49c3-b59a-b799c379cebb/c99-variable-length-array-is-unsupported-and-give-bad-error-message?forum=vcprerelease#3b6b14b0-e9f0-47b2-abb1-79d46c004212-isAnswer) and [they will not be added](https://devblogs.microsoft.com/cppblog/c11-and-c17-standard-support-arriving-in-msvc/#variable-length-arrays).

I think (but I don't have insider information) that the difficulties with VLA aren't in implementations, but for users. [VLAs are bug-prone for many reasons](https://stackoverflow.com/questions/1018853/why-is-the-use-of-alloca-not-considered-good-practice). An obvious one is that they can very easily lead to a stack overflow, which often has disastrous consequences (at best a crash, often memory corruption). Another consequence is that innocuous-looking constructs such as `sizeof(...)` may now have side effects, and even a simple `sizeof(a)` doesn't actually return the size of the array `a` if it's a VLA function parameter (that's true if it's a function parameter as well with a static size, but VLAs make it look more like it should work).

Another reason against having VLA in the C standard is that [according to John Nagle on comp.std.c](https://groups.google.com/g/comp.std.c/c/AoB6LFHcd88/m/BvA4NiBe2mcJ),

> Prototypes of functions with VLA parameters do not have to exactly match the function definition. This is incompatible with C++ style linkage and C++ function
> overloading, preventing the extension of this feature into C++.

C++ is mostly an extension of C; it tweaks some behavior (enough that most idiomatic C programs aren't valid C++) but having a major feature of C that's not in the next edition of C++ is unusual, and is problematic for compilers that handle both languages (which is most C++ compilers).

From personal experience in as a C programmer on embedded platforms, we never use VLAs, even when we're sure that all compilers we care about would support them. They're too bug-prone and they make it impossible to predict your program's stack size (we like to make sure that the deepest nesting of function calls will not overflow the stack — we don't use recursion either). [Jens Gustedt on comp.std.c](https://groups.google.com/g/comp.std.c/c/AoB6LFHcd88/m/V-3kJfQ3VYgJ) also cites GPUs as a type of platforms where VLAs aren't welcome (I don't know exactly why, but I guess because the memory assigned to each thread's stack tends to be limited).
> **Comments:**
> **username_4** (2023-06-16): "in Visual C++, they were one of the last C99 features to be added." -- It's my understanding that it _still_ doesn't fully implement C99, if nothing else because it doesn't understand the `restrict` keyword (you have to write `__restrict` instead).  
> **username_3** (2023-06-16): @Bbrk24 In fact VS doesn't implement VLAs at all (I realize what I wrote is a bit misleading). They never really tried to implement C99 and went directly to C11.  
> **username_5** (2023-12-13): No version of the C Standard has ever specified as a condition of conformance that an automatic-duration object definition of the form `int arr[n]` behave meaningfully for any particular value of `n`, nor specified what should happen if `n` exceeds the maximum value an implementation can handle.  The only real effect of making the feature optional is that implementations that wouldn't otherwise support VLAs of non-trivial size needn't waste effort pretending to support them, and can instead reject at compile time programs that would be unlikely to behave usefully at run time.  
---
### Answer by username_6 on 2023-06-11. Score: 13
I'd say one of the reasons is that it was a rather niche feature with a very natural syntax (which you usually try to avoid). Most times I've seen VLAs used in code, it was by novice programmers who didn't care much about how it worked and just preferred it to the more verbose heap allocations. Another common case is people intending to encapsulate the array size in a compile-time variable, but forgetting(/not realizing the need) to mark it as `constexpr` or at least `const`. There's little benefit to a feature like this, and it introduces confusion to users and complexity to the language (like, as you've mentioned, having `sizeof` operate at runtime in some cases). It's a much more fitting solution to provide the `alloca` function as the API for stack allocations for cases when it is actually needed, and have the programmers handle the resulting variable-length array by pointer, same as in other cases.

As for whether the implications can be avoided, I'd say, possibly, but not in the general case. If, for instance, the base-pointer optimization is enabled (making the local variables be resolved through the stack pointer instead of the base pointer), any VLA significantly slows down the local variable access (as it needs to perform at least one more operation every time). Overall, perhaps some clever tricks could be introduced, but VLAs seem to be of too little use to overcome such difficulties for.

Also worth noting is that a similar concept of variable-sized structs (i.e. having an array extend past the end of a struct) is a widely used idiom in C/C++, despite having almost no specific language support (like no special cases for `sizeof` nor automatic copying).

**TL;DR**: `alloca` does the trick just as well, but is less confusing both for users and language designers
---
### Answer by username_2 on 2023-06-13. Score: 3
I recall this feature being a GNU extension for a long time before becoming standardized. I suspect it was implemented using alloca() or similar to allocate space on the stack.
This is certainly born out by the Wikipedia page on the subject.
There is a very good quality answer to this question here.
It's easily missed as its asked in the context of C++.
The big danger is the simple and obvious implementation is dangerous.
For example:
foo(int n)
{
   int someArrayOnTheStack[n];
   // do stuff
}

You can easily overflow the stack if n is big. In our security conscious world that's a buffer overflow exploit waiting to happen.
You can get around that by allocating on the heap instead but that defies users expectations as it looks like a stack declaration but magically becomes a heap one with no visible call to malloc().
Of course in C++ you'd just write:
foo(int n)
{
   std::vector someArray(n);
   // do stuff
}

Which matches expectations and so the feature is unnecessary there.
The linked Q&A points out some other issues.
---
