Automatic storage duration

From cppreference.com
< c‎ | language

An object whose identifier is declared with no linkage and without the storage-class specifier static has automatic storage duration, as do some compound literals. The result of attempting to indirectly access an object with automatic storage duration from a thread other than the one with which the object is associated is implementation-defined.

For such an object that does not have a variable length array type, its lifetime extends from entry into the block with which it is associated until execution of that block ends in any way. (Entering an enclosed block or calling a function suspends, but does not end, execution of the current block.) If the block is entered recursively, a new instance of the object is created each time. The initial value of the object is indeterminate. If an initialization is specified for the object, it is performed each time the declaration or compound literal is reached in the execution of the block; otherwise, the value becomes indeterminate each time the declaration is reached.

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. If the scope is entered recursively, a new instance of the object is created each time. The initial value of the object is indeterminate.

A non-lvalue expression with structure or union type, where the structure or union contains a member with array type (including, recursively, members of all contained structures and unions) refers to an object with automatic storage duration and temporary lifetime. Its lifetime begins when the expression is evaluated and its initial value is the value of the expression. Its lifetime ends when the evaluation of the containing full expression or full declarator ends. Any attempt to modify an object with temporary lifetime results in undefined behavior.

[edit] Example

The object named "a" does not have a variable length array type. Function f() makes a new instance of the object named "a" with each recursive entry.

#include <stdio.h>
 
void f (int ctr)
{
    if (ctr == 0) return;
    int a = 0;   /* initialization happens each time this declaration is reached */
    ++a;
    printf("f():     %p %d\n", (void*)&a,a);
    f(--ctr);
    return;
}
 
int main(void)
{
    /* Declare two variables having automatic storage duration. */
    int a = 0;
    auto int b = 0;
 
    { /* suspend execution of current block with entry into an enclosed block */
      int a = 0;
      printf("main():  %p %d\n", (void*)&a,a);
    }
 
    f(3);   /* suspend execution of current block with a function call */
 
    printf("main():  %p %d\n", (void*)&a,a);
 
    return 0;
}

Possible output:

main():  0x7fff3b00354c 0
f():     0x7fff3b00352c 1
f():     0x7fff3b00350c 1
f():     0x7fff3b0034ec 1
main():  0x7fff3b003548 0

[edit] Example

The object named "a" has a variable length array type. Function f() makes a new instance of the object named "a" with each recursive entry.

#include <stdio.h>
 
void f (int N)
{
    if (N == 0) return;
    int a[N];   /* new instance of object a */
    printf("f():  %p %2zu\n", (void*)&a,sizeof(a));
    f(--N);
    return;
}
 
int main(void)
{
    f(3);   /* recursive function call */
 
    return 0;
}

Possible output:

f():  0x7fff592882f0 12
f():  0x7fff592882c0  8
f():  0x7fff59288290  4

[edit] Example

The object returned by function f() is a non-lvalue expression with structure or union type, where the structure or union contains a member with array type. This temporary object has a lifetime that is equal to the duration of the printf() function call; its lifetime ends when printf() returns.

#include<stdio.h>
 
typedef struct array_in_struct array_in_struct;
struct array_in_struct {
    char s[7];
};
 
array_in_struct f (void) {
    array_in_struct ais = {"qwerty"};
    return ais;
}
 
int main(void)
{
    printf("%s\n", f().s);
 
    return 0;
}

Possible output:

qwerty