17

When VLAs were introduced in C 1999, I thought it was a great innovation to the language. However, having learned it was made optional in C 2011, I am wondering what led to its change in status, and if it means the feature is actually headed for obsolescence. If so, is there an equivalent notion of automatic management of dynamically sized data that is being considered to replace it?

I attempted to find the C 2011 rationale document, but it does not seem to be published yet.

jxh
  • 479
  • 3
  • 10

2 Answers2

9

I've heard legends varying from "it should be optional as some small compilers should be able to be C11-compliant without VLAs" to "it was a mistake on the first place". I've never got one true and definite answer to this, though. Ultimately, I don't believe anyone really has one as the reason (assuming - and hoping - there is one) was never disclosed (as far as my old searches went).


From Chapter 4 (page 13) of Rationale for International Standard - Programming Languages - C 5.10 (2003)

By defining conforming implementations in terms of the programs they accept, the Standard leaves open the door for a broad class of extensions as part of a conforming implementation. By defining both conforming hosted and conforming freestanding implementations, the Standard recognizes the use of C to write such programs as operating systems and ROM-based applications, as well as more conventional hosted applications. Beyond this two-level scheme, no additional subsetting is defined for C, since the C89 Committee felt strongly that too many levels dilutes the effectiveness of a standard.

Emphasis mine. Notice that this decision goes against their own rationale. Yet, another thing made optional. Now you either get __STDC_NO_VLA__ or VLA support. It is a very odd decision.

  • @jxh Didn't even see that. Thanks for pointing it out, it has been changed to a clearer and less ambiguous wording. I've seen motif as a synonym of motive and goal in some contexts, but I believe it is only common in artistic scenarios. – Bernardo Sulzbach Apr 05 '16 at 23:51
  • The problem with having only a two-level scheme is that there are many useful features and guarantees which are widely but not quite universally supported, and which may allow some kinds of programs to be written much more efficiently than would otherwise be possible. The lack of any standard means of testing for the availability of such features makes it necessary for a significant fraction if not a majority of practical programs in many fields to make use of guarantees beyond those included in the Standard, and makes it difficult to determine with certainty whether any particular... – supercat Apr 21 '16 at 19:31
  • ...program will work with any particular implementation. Defining a larger variety of optional features and guarantees which implementations can either support or refuse (by rejecting compilation) would make it possible to have a nice easy standard way of testing whether a program which properly specifies its requirements will work correctly on a platform: try to build it. If it builds, it will work. If not, it obviously won't. Increasing the fraction of programs for which it would be possible to guarantee that a successful build would guarantee successful operation... – supercat Apr 21 '16 at 19:34
  • ...would seem far more valuable than merely maximizing the number of compilers that can handle the tiny fraction of programs that wouldn't benefit from features and guarantees beyond what the Standard requires. – supercat Apr 21 '16 at 19:35
7

As far as I can determine from the public committee documents (in particular N1395), one of the major reasons for making VLA's (along with complex arithmetic and threading) optional was to make it possible to create conforming C compilers for small embedded processors.

The trend was that the compiler vendors that target embedded systems were staying on the C90 standard, because of the introduction of those large features that their customers weren't asking for.

Bart van Ingen Schenau
  • 71,712
  • 20
  • 110
  • 179
  • In many cases, "were asking to have left out". Once you look at the RAM footprint change when you enable those features it becomes obvious why some people don't want them. It can double the cost of the processor, which can be the most expensive part of the system. – Ⴖuі Apr 06 '16 at 07:53
  • VLAs don't use more RAM, but less. Say a colour lookup table with either 16 or 256 entries. Where instead of declaring an array with 256 entries, I declare it with the right size. And if you don't use the feature, it doesn't cost anything. The problem is the compiler. – gnasher729 Apr 06 '16 at 13:40
  • @gnasher729: That's not entirely true. If you use `sizeof` on a VLA, the size has to be computed at run time, so you typically have either extra data to store the size, or extra code to compute it. Either way, there's at least some possibility of code and extra storage being used. – Jerry Coffin Apr 06 '16 at 16:30
  • @mafagafogigante points to the rationale for freestanding vs. hosted implementations, which was already supposed to cover this need for embedded C compilers. – jxh Apr 06 '16 at 17:56
  • 1
    @JerryCoffin: Yes, but the code is only generated when sizeof() is actually used on the array. The compiler needs to track the info so it can generate the correct code, but that info need not be embedded into the in memory representation of the VLA. – jxh Apr 06 '16 at 18:06
  • 2
    @jxh: As originally envisioned, freestanding and hosted implementations used the same core language. The differences were restricted to the library. In the case of VLAs, there's a difference in the language itself that (at least some vendors felt) wasn't really suitable to smaller embedded systems. As far as embedding the size goes: no, it's probably never absolutely necessary, but may be the easiest way (e.g., a few bytes of storage for the size might avoid many bytes of code to compute it). – Jerry Coffin Apr 06 '16 at 18:10
  • @JerryCoffin: Well, the definition of core language is little vague. Freestanding implementations were not required to use `main()` as the program entry point, which *seems* core (although it could *seem* library-ish from a different point of view). – jxh Apr 06 '16 at 18:16
  • @jxh: Fair enough--it certainly looks/seems like library to me, but I guess I can see a viewpoint from which it would seem like the core language. In any case, it's the name of a function, not the expressions/statements you can write in that function, which is the difference here. I think there'st waning concern over subsets though. When C89 was new, BASIC and Pascal had both fragmented badly, part due to a number of dialects of each (if memory serves, at least three standards each, all ignored in the wider market). – Jerry Coffin Apr 06 '16 at 18:21
  • So, why weren't the compiler vendors happy enough with staying on C 1990 if their customers were happy with it? – jxh Apr 06 '16 at 18:46
  • @jxh: While it would certainly be possible for a compilers to advertise themselves as "C89 plus some features from C11", having a modern standard to which compilers can claim conformance is more helpful. Actually, if one wants C to be meaningful as a unified standard, it needs a lot more optional-but-testable behaviors, such that it would be possible for most programs to be written in a way that they would not be guaranteed to build on all platforms, but could be guaranteed to work correctly on all Standard-compliant platforms where they build. – supercat Apr 21 '16 at 19:27
  • 1
    @supercat: I can see the logic of cherry picking C library functionality, but making language features "optional" seems decidedly unhelpful to someone trying to write multi-platform C code. It *used* to be that C was the obvious choice for close to metal systems programming that could easily be retargeted to a different compiler and different hardware platform. Now, it is not so obvious. – jxh Apr 21 '16 at 19:46
  • @jxh: If it is recognized that "optional" means "Define this if your customers will benefit from having it defined", the set of reliable behaviors that would be available for code targeting most common platforms would be far greater than it is today. Even if a few presently-mandated features and guarantees were made optional, I would expect that the only implementations that wouldn't define them would be those that wouldn't otherwise be able to support the language at all. – supercat Apr 21 '16 at 19:54
  • @supercat: One "feature" of language standards is that relying on an older standard will likely result in higher probability of successful retargeting the application to a new platform that has a new compiler. C 2011 kind of flushes that down the toilet. It sets the precedent that any feature in any present standard may get turned into an optional one in a future standard. Obsolescence can't be helped, of course, and I do ask about that in my posted question. – jxh Apr 21 '16 at 20:23
  • 1
    @jxh: C99 erred in adding mandatory features for which there was no demonstrated demand, and for which adding support would in some cases not be cheap [for some compilers, adding support for complex numbers might require a major reworking of the type-system code, especially if they use tricky bit codings for primitive types and such encodings don't have room for more choices]. A better route to take would be to start by making features optional and then seeing which ones end up getting used. If the Standard defines an optional feature before compiler vendors start providing... – supercat Apr 21 '16 at 20:59
  • ...similar functionality on their own, then implementations will likely be compatible. Otherwise, one ends up with messy situations like the layout of `struct foo {int32_t x; int8_t y; uint8_t z[];}`. On a system with 32-bit alignment, what should be the size of `struct foo`, and the offset of `z`? If Flexible Array Members had been defined by the Standard before compilers writers started implementing them on their own, such things could be defined by the Standard. As it is, such things are rather murky. – supercat Apr 21 '16 at 21:02
  • 1
    @supercat: Introducing new features as optional is okay as a compromise for standards moving forward. But, it is not clear C will always do that, and it didn't do that for 2011. For example `_Generic` might be made optional in the future. So, the portable strategy is to not write code that uses it. Thus, it never gets used, and is not demanded. Then it gets retroactively made optional in the next standard. Yay. – jxh Apr 21 '16 at 21:12
  • @jxh: Has the fact that complex types are optional caused a massive number of C11 compilers to refrain from supporting them even though they could? – supercat Apr 21 '16 at 22:32
  • @jxh: As for VLAs, has any version of the Standard ever mandated that any implementation be able to create one larger than a single element without bombing the stack? If not, that means that useful support for VLAs over a single element is and always has been optional, and I would suggest that an implementation that rejects code that tries to use a VLA should be considered preferable to one that allows such code to compile but then fail at runtime. – supercat Apr 21 '16 at 22:48
  • 2
    @supercat: Bombing the stack is not unique to VLA. Abnormally large automatic objects or an unrestrained function call stack will have similar issues. If the standard defines a means to detect failure for those cases, it would likely work for VLA as well. In terms of optional, it just makes it harder to argue for using new C features in new C code in new projects that are required to work on multiple platforms using compilers from multiple vendors. – jxh Apr 21 '16 at 23:29
  • @jxh: If the Standard never required implementations to support VLAs larger than a single element without UB (and from what I can tell, it didn't), then run-time support has *always* been optional. I'd rather have the Standard say that compilers are allowed to reject VLAs at compile-time if run-time support would be lacking, than say that they must compile the code but may then invoke UB if code tries to use the arrays. While it's true that other things can blow the stack, VLAs create a situation where "int a[n]" is *expected* to blow the stack for some values of n, but... – supercat Apr 22 '16 at 14:22
  • ...implementations are under no obligation to indicate whether the critical value is 2, 2000, or 200000000. The platforms I've used with the most limited stacks squawk at recursion (another feature I think should be optional, BTW) but that allows them to compute exact stack requirements and guarantee that programs which compile will not blow the stack. On such platforms, a VLA which could hold up to 16 elements [even if a compiler knew the upper limit] would offer no advantage over a 16-element array. – supercat Apr 22 '16 at 14:27
  • @supercat: Good point. The standard should state minimum limits for arrays allocated for VLA. Pointers to VLA should not be as constrained. – jxh Apr 22 '16 at 14:48
  • @jxh: More useful, I would think, would be for the Standard to specify that if an implementation supports VLAs it must either provide a means by which code can determine when they will be safe to use, or provide a means via which a programmer can explicitly waive such assurances (the latter being included to allow an upgrade path for C99 compilers which worked usefully without crashing often enough that programmers found them useful, but lacked any mechanism for providing operational assurances). – supercat Apr 22 '16 at 14:56