Variable Length Arrays in C99

A Variable Length Array (VLA) is a construct introduced starting from the C99 standard in the C language.

Variable length arrays allow defining arrays whose size is determined at runtime and not at compile time. However, the size of a VLA cannot be modified after its declaration.

In this lesson we will see how to define and use variable length arrays in C99. We will see which expressions are admissible for the length of a VLA, how to define multidimensional arrays and what the usage limits are.

The Problem of Fixed Length of an Array

We have seen in the lesson on static monodimensional arrays, and also in the one on static multidimensional arrays, that the size of an array must be known at compile time.

To indicate the size we have seen that there are two ways:

  • Indicating it explicitly during declaration:

    /* Creates an array of 10 elements */
    int a[10];
    
  • Deriving it from the number of elements in the initialization list:

    /* Creates an array of 3 elements */
    int a[] = {1, 2, 3};
    

In both cases, however, the length of the array is determined by a constant expression.

The problem of having a length known at compile time is that assumptions must be made about the size of the array, which might not always be verified. In other words, the developer with this approach must predict what the necessary maximum length of the array is.

But, in doing so, the developer could choose a length that is too small, causing a buffer overflow, or too large, wasting memory.

To solve this problem there are two approaches:

  • The first is to use dynamic memory allocation. This topic, however, deserves a separate chapter and we will study it in the next lessons. Also because, to fully understand it, it is necessary to first study pointers.
  • The second approach is to use variable length arrays defined starting from the C99 standard. They are the topic of this lesson.

Variable Length Arrays in C99

Starting from the C99 standard it is no longer necessary for the length or dimensions of an array to be known at compile time.

Instead, it is possible to use, in some cases, non-constant expressions to define the length of an array.

Let's see an example. Suppose we want to create a program that calculates the sum of n integer numbers entered by the user. In this case, n is a value that is not known at compile time but must be requested from the user.

We can implement the program in this way:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>

int main(void) {
    int n;

    printf("Enter the number of elements: ");
    scanf("%d", &n);

    /* Creates an array of n elements */
    int a[n];

    for (int i = 0; i < n; i++) {
        printf("Enter the %d° number: ", i + 1);
        scanf("%d", &a[i]);
    }

    int sum = 0;

    for (int i = 0; i < n; i++) {
        sum += a[i];
    }

    printf("The sum of the entered numbers is: %d\n", sum);

    return 0;
}

The key point is placed in lines 9 and 10. Here we are defining the array a as an array of n int elements. But the value of the variable n is not known at compile time.

The value of n will be set only after the user has entered the number of elements.

Arrays of this type are called Variable Length Arrays or Variable Length Array (VLA).

The size of a VLA is determined at runtime, not at compile time. The important thing is that the value is known at the moment the array is declared.

The main advantage of using VLAs is that memory can be saved, as exactly the necessary amount of memory can be allocated. Assumptions about the maximum size of the array do not need to be made.

Definition

Variable Length Array in C99

Variable Length Arrays, also called Variable Length Array (VLA), are arrays whose size is determined at runtime and not at compile time.

They were introduced in the C99 standard.

The constraint for their use is that, at the moment of their declaration, the expression that defines their length is known.

Admissible Expressions for the Length of a VLA

To define a VLA it is not necessary to use only a variable.

In fact, more complex expressions can be used, provided that the value is known at the moment of the array declaration.

For example, the following expressions are admissible:

int a[m + n];
int b[2 * m];
int c[(m + n) * 2];

In the above expressions, however, the following conditions must be met:

  1. The variables m and n must be defined and initialized before the array declaration;
  2. The result of the expressions is a positive value greater than zero.
Definition

Admissible Expressions for the Length of a VLA

To define a VLA the following syntax is used:

type array[expression];

Where expression is an expression such that:

  1. The variables used in the expression are defined and initialized before the array declaration;
  2. The result of the expression is a positive value greater than zero.

Multidimensional Variable Length Arrays

Variable length arrays can also be multidimensional.

For example, we can define a matrix of dimensions m \times n in this way:

double matrix[m][n];

Obviously, provided that m and n are variables defined and initialized before the array declaration.

Furthermore, the dimensions of a multidimensional VLA can also be greater than two.

Definition

Multidimensional Variable Length Arrays

A Variable Length Array in C99 can also be multidimensional.

The syntax for declaring a multidimensional variable length array is the following:

type array[expression1][expression2];

Where for the two expressions expression1 and expression2 the same rules seen for monodimensional arrays apply.

Notes on Length Variability

We said that the length of a VLA must be known at the moment of the array declaration.

However, we must deepen some issues related to the variability of the length of a VLA.

The term variable length of an array can be misleading. It can, in fact, lead to thinking that the dimensions of an array can be modified at any time after it has been defined. But this is not true.

In particular, the size of a VLA cannot be modified after its declaration, even if it is calculated at runtime.

So, for example, if we have an array a defined as:

int a[n];

and when we reach this definition n is worth 5, the length of a will be worth 5. Even if later n should change, the size of a will always remain 5.

Therefore, a more appropriate name for VLAs would be Arrays with Length Defined at Runtime.

However, this does not limit their use. They are widely used inside functions.

We have not yet studied user-defined functions and the visibility rules of variables, so we must anticipate some concepts.

When a VLA is defined inside a function, its size is valid only within that function. When the function ends, the memory allocated for the array is freed.

So, every time that function is invoked, the array changes size.

For example:

int example(int n) {
    /* Every time the 'example' function is called
     * the array a changes size
     */
    int a[n];

    /* Rest of the code */
}

In this example, every time the example function is called, the array a changes size based on the value of n.

Actually, to be correct, it is not that a changes size; what happens is that a new array is created that is always called a but with different size.

In any case, we will study functions and variable visibility thoroughly in the next lessons.

Definition

Variability of the Length of a VLA

The size of a VLA is defined at the moment of its declaration and cannot be modified later.

Limits of Variable Length Arrays

Variable length arrays were introduced in the C99 standard to solve the problem of fixed length arrays.

But they have some limitations in their use.

  • The first limit is that they cannot be used as global variables.

    We will study global variables in the next lessons. For now, we know that global variables are defined outside all functions and are visible throughout the program.

    So far, the variables we have used are local variables because they are defined inside the main function.

  • The second is that they cannot be declared as static.

    We have not yet studied static variables. We will study them in the next lessons.

  • Initialization lists cannot be used.

    Variable length arrays cannot be initialized with a list of values.

    For example, the following declaration is incorrect:

    /* ERROR */
    int a[n] = {1, 2, 3};
    

    This is because the initialization list could have a size smaller than that of the array.

  • The definition of a VLA cannot be bypassed with the goto instruction:

    /* ERROR */
    goto end;
    int a[n];
    end:
    

    This is because, instructions after the destination point of a goto could access a which has not yet been defined and therefore allocated.

Conclusions

Variable length arrays are a feature introduced in the C99 standard to solve the problem of fixed length arrays.

They allow defining arrays whose size is determined at runtime and not at compile time.

VLAs are very useful inside functions, as their size is valid only within the function itself.

However, they have some limitations, such as the fact that they cannot be declared as global variables, they cannot be declared as static, they cannot be initialized with a list of values and they cannot be bypassed with the goto instruction.

Furthermore, the size of a VLA cannot be modified after its declaration.