12

Let us consider the following code:

#include <stdio.h>

int main(){
    int size,i;
    scanf("%d",&size);
    int x[size];

    for(i=0;i<size;i++){
        x[i] = i;
    }

    for(i=0;i<size;i++){
        printf("%d\n", x[i]);
    }

    return 0;
}

I think that there are versions in that we cannot declare an array using a variable for defining its size, like in:

int x[size];

But I'm not sure about which version is. This is allowed in the so called ANSI C?

5
  • In fact, the very ability to declare new variables somewhere other than at the start of a scope is not permissible in C89. Commented Apr 15, 2019 at 20:24
  • 2
    This is a so-called "Variable Length Array" that was made a part of a language in C99 standard revision, but was made optional in C11
    – Eugene Sh.
    Commented Apr 15, 2019 at 20:25
  • related: stackoverflow.com/questions/6629394/… Commented Apr 15, 2019 at 20:27
  • I don't think this counts as a duplicate. This is asking for clarification about which version(s) of C support this feature, whereas the other question is asking how variable length arrays work. Commented Apr 15, 2019 at 20:39
  • 1
    the answers there explain the standard where VLAs appeared. This is 2019. We have enough C duplicates. Commented Apr 15, 2019 at 20:40

4 Answers 4

14

In C89/C90, you can't interleave declarations and statements, such as putting the int x[size]; declaration (definition) after the scanf() — even if you change the dimension to a compile time constant. In C89/C90, declarations within a function must appear at the start of a compound statement (immediately after the { and before the first statement within the compound statement; compound statements can be nested within a function body).

In C89/C90, you cannot use a variable length array — so the int x[size]; definition is not legal because size is not a compile time constant.

C99 compilers are required to support both declarations at (almost) arbitrary points in a function (they still can't be preceded by a label) and variable length array (VLA) definitions.

C11 compilers are required to support variable definitions (almost) anywhere in a function. C11 compilers may optionally support VLAs (§6.10.8.3 Conditional feature macros and §6.7.6.2 Array declarators), and should define __STDC_NO_VLA__ if they do not support them.

C18 is equivalent to C11 in all aspects of this discussion.

When it is released, C23 will require that compilers accept VLA specifications as function arguments but will not require that local variables can be defined as VLAs. You will be able to dynamically allocate VLAs as now — and on restrictive compilers, will be required to do so.

Just for the record:

  • C89 is ANSI X3.159-1989
  • C90 is ISO 9899-1990 — the ANSI version of which was marked with "revision and redesignation of ANSI X3.159-1989". The primary difference was in the section numbers for the language and the library.
  • C99 is ISO/IEC 9899:1999
  • C11 is ISO/IEC 9899:2011
  • C18 is ISO/IEC 9899:2018
  • C23 will be either ISO/IEC 9899:2023 or 9899:2024.

Of course, the only unusual thing about X3.159-1989 was that it was published by ANSI before there was an ISO standard. However, ANSI has adopted each subsequent ISO standard too, as have other national standards bodies such as BSI (British Standards Institute) and DIN (Deutsches Institut für Normung or German Institute for Standardization).

There was also an Amendment 1 (to ISO 9899:1990) finalized in 1994 and published in 1995. That added headers and introduced digraphs and made sundry other changes. It is almost never considered separately, especially not now, 25 years later.

Note that GCC treats the -ansi option as equivalent to -std=c90, which can lead to confusion over terminology. ANSI originally published 'the ANSI C standard' a year or so before ISO did, but the intent was always to have a common standard, and ANSI endorsed the ISO 9899:1990 standard when it was published.

6
  • About interleaving statements and declarations, you could still have nested scope blocks in {}, and you could declare new variables at the beginning of any such block, so it would have been possible to read size, then declare VLA of that length in a nested block after that. ...or am I mistaken?
    – hyde
    Commented Apr 15, 2019 at 21:14
  • @hyde: yes, you could define variables at the start of any statement block. In C89/C90, you could not have a variable-length array even if the size was determined in an outer block and the array defined in an inner blcok; the dimensions of an array had to be fully determinate at compile time (by definition using constants for all the dimensions, or by initialization to allow the first dimension to be unspecified). The only way to dynamically size an array was via dynamic memory allocation — malloc() et al. The rules all changed in C99. Commented Apr 15, 2019 at 21:18
  • You may want to mention that ANSI has been adopting the more recent ISO/IEC standards and not just ISO 9899:1990. This just perpetuates the confusion that ANSI-C refers just to first revision. stackoverflow.com/a/4232714/1028434
    – fdk1342
    Commented Apr 15, 2019 at 22:20
  • @Fred: I've added a paragraph to emphasize that national standards bodies such as ANSI, BSI, DIN adopt ISO standards. Whatever may be the case in other areas of the world affected by ISO and ANSI, in the C world, 'ANSI C' refers to C89 and ISO C can be used to contrast the later standards. At one level I agree with you; at another level, I think you are pushing against a close to immovable object. Commented Apr 15, 2019 at 22:42
  • Yep (regarding my earlier comment), but the wording of first paragraph could be changed, because you could put the declaration after the scanf by adding a nested block. I'm rising this point, because many seem to think you had to define all variables at the start of a function.
    – hyde
    Commented Apr 16, 2019 at 4:48
5

This is how support for variable-length arrays (VLA) has changed in C over the years:

  • "C90" ISO 9899:1990+AMD1:1995 (aka "C89", ANSI X3.159, "ANSI C", AMD1 = "C95")

    No support for variable-length arrays.

  • "C99" ISO 9899:1999

    Variable length arrays were added as a new, mandatory feature.

  • "C11" ISO 9899:2011 and "C17" ISO 9899:2018 (aka "C18")

    Variable length arrays were relaxed to an optional feature. Compilers may define the macro __STDC_NO_VLA__ to indicate that they do not support any form of variable length arrays.

  • "C23" ISO 9899:20xx (aka "C2x") - upcoming ISO standard in 2023.

    Pointers to variable length arrays are once again made mandatory as in C99. __STDC_NO_VLA__ is now only used to indicate that variable array objects with automatic storage duration are not supported.


C11/C17 wording (6.10.8.3):

__STDC_NO_VLA__ The integer constant 1, intended to indicate that the implementation does not support variable length arrays or variably modified types.

C23 wording (n3054-5 draft 6.10.9.3):

The integer constant 1, intended to indicate that the implementation does not support variable length arrays with automatic storage duration. Parameters declared with variable length array types are adjusted and then define objects of automatic storage duration with pointer types. Thus, support for such declarations is mandatory.

0

ANSI-C (C89) does not allow initialize an array using a variable.

For example:

  int x = 5;
  int ia[x];

This above example is illegal. ANSI-C restricts the array intialization size to be constant. However you can use macros to define the length of an array.

Example:

    #define MAX_ARRAY_SIZE 5
    int ia[MAX_ARRAY_SIZE];
9
  • 3
    erm C99 allows variable length arrays. Commented Apr 15, 2019 at 20:25
  • 1
    the answer is incomplete and not mentionning C99 VLAs. Question is a clear dupe anyway. Commented Apr 15, 2019 at 20:33
  • 1
    According to the ANSI website: The Current C Programming Language Standard – ISO/IEC 9899:2018 (C18). So when people refer to the ANSI standard it isn't just limited to C89.
    – fdk1342
    Commented Apr 15, 2019 at 20:55
  • 2
    @Fred: In common parlance, partially enforced by the GCC compiler, ANSI standard means the C89 standard X3.158-1989, released before the ANSI/ISO 9899-1990 standard was released (marked with "revision and redesignation of ANSI X3.159-1989"). The main difference was the section numbers in the ANSI and ISO standards. GCC encourages this confusion because the option -ansi is equivalent to -std=gnu90, and so many people regard "ANSI C" as the C89 or C90 standard — they're effectively equivalent standards. Quibbling otherwise doesn't actually help anyone very much. Commented Apr 15, 2019 at 21:02
  • 1
    @JonathanLeffler Maybe you think it's common, that's fine, but I disagree. The common practice I've seen is that ANSI-C refers to the standard as opposed to additional extensions supported by the compiler. Also according to GCC manual -ansi is equivalent to -std=c90 NOT -std=gnu90. So even here ANSI refers to not using GNU dialect and certain GNU extensions. I would have to say that your comment isn't very helpful either.
    – fdk1342
    Commented Apr 15, 2019 at 21:49
0

This kind of array, called variable length array was added in C99 as one of the major changes mentioned in the Foreword on page xi of the C99 draft N1256.

The details are then in §6.7.4.2, "Array declarators" on page 116 of the linked document.

Check out this nice article about modern C programming:

https://matt.sh/howto-c

3
  • 1
    +1 for having a correct (if pithy) answer, -1 for the link to a top-level entry point for a wide-ranging resource as opposed to pointing to (1) a narrower location within a resource; or (2) letter-and-verse of the relevant spec (or finding something licensed to be quotable in-answer and thus able to survive link breakage). Commented Apr 15, 2019 at 20:30
  • That's a nice observation. Pointing to the specific spec in the language reference would be more reliable for the readers. Writing the tip down for my future answers. Commented Apr 15, 2019 at 20:35
  • It would have been great to find the chapter of the C99 spec where this is defined. Commented Jan 13, 2023 at 9:08

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.