Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C Variable Length Arrays storage duration

Tags:

c

scope

On this site there is the following paragraph (emphasis mine):

  • automatic storage duration. The storage is allocated when the block in which the object was declared is entered and deallocated when it is exited by any means (goto, return, reaching the end). One exception is the VLAs; their storage is allocated when the declaration is executed, not on block entry, and deallocated when the declaration goes out of scope, not than when the block is exited (since C99). If the block is entered recursively, a new allocation is performed for every recursion level. All function parameters and non-static block-scope objects have this storage duration, as well as compound literals used at block scope.

What is the difference between a declaration going out of scope and a block being exited? Can you provide an example?

like image 480
user42768 Avatar asked Jan 18 '18 18:01

user42768


People also ask

Does C allow variable length arrays?

C supports variable sized arrays from C99 standard.

Is VLA allowed in C?

In C, the VLA is said to have a variably modified type that depends on a value (see Dependent type). The main purpose of VLAs is to simplify programming of numerical algorithms.

Can a static array have variable size?

You cannot declare a static array of variable size because its space is allocated in the Data Segment (or bss segment in case of an uninitialized variable). Hence the compiler needs to know the size at the compile time and will complain if the size is not a constant.

How do you declare a variable sized array?

If you want a "variable length array" (better called a "dynamically sized array" in C++, since proper variable length arrays aren't allowed), you either have to dynamically allocate memory yourself: int n = 10; double* a = new double[n]; // Don't forget to delete [] a; when you're done!


2 Answers

From the N1570 draft of the C11 specification §6.2.4/7

For such an object that does have a variable length array type, its lifetime extends from the declaration of the object until execution of the program leaves the scope of the declaration.

The specification then adds this helpful note:

Leaving the innermost block containing the declaration, or jumping to a point in that block or an embedded block prior to the declaration, leaves the scope of the declaration.

So the VLA is de-allocated when the execution goes outside the scope of the VLA, which includes the section in the same block before the declaration of the VLA.

Jumping to a point prior to the declaration can be done with a goto statement. For example:

int n = 0;
while (n < 5)
{
top:
    n++;
    char array[n];
    if (n < 2)
        goto top;
}

In this code, the block is not exited when the goto is executed. However, the value of n changes, so a new array needs to be allocated. That's the horribly convoluted situation that the specification is trying to support.

like image 82
user3386109 Avatar answered Sep 22 '22 08:09

user3386109


What is the difference between a declaration going out of scope and a block being exited? Can you provide an example?

The scope of a block-scope identifier starts at its declaration and extends to the end of the innermost enclosing block. This applies to identifiers of every kind, not just those of VLAs. It is possible for control to leave the scope of an identifier without exiting the innermost block containing it by transferring to a point preceding the identifier's declaration. The most obvious way to accomplish that would be via a goto statement:

int f(int n) {
    // i is allocated here, _before_ the beginning of its scope
    label: // if control returns here via the goto below, vla is _de_allocated
           // at this point
    printf("n is %d", n);

    int vla[n]; // vla is (re)allocated here, at the beginning of its scope
    int i;
    int sum;

    for (i = 0; i < n; i++) {
        vla[i] = rand();
        sum += vla[i];
    }

    if (sum < SOME_THRESHOLD) goto label; 

    return sum;  // vla and i are both deallocated when control exits the block
}

The difference in when a VLA is deallocated vs. when an ordinary automatic object is deallocated mirrors the difference between when the two types of objects are allocated. VLA's live only within the scope of their identifiers.

like image 36
John Bollinger Avatar answered Sep 22 '22 08:09

John Bollinger