Using int a;
inside a function is described by C 2018 6.2.4 5:
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…
Paragraph 6 continues:
… The initial value of the object is indeterminate…
An indeterminate value is not an actual specific value but is a theoretical state used to describe the semantics of C. 3.19.2 says it is:
… either an unspecified value or a trap representation…
and 3.19.3 says an unspecified value is:
… valid value of the relevant type where this document imposes no requirements on which value is chosen in any instance…
That “any instance” part means that the program may behave as if a
has a different value each time it is used. For example, these two statements may print different values for a
:
printf("%d\n", a);
printf("%d\n", a);
Regarding const int b = a;
, this is not covered explicitly by the C standard, but I have seen a committee response: When an indeterminate value is assigned (or initialized into) another object, the other object is also said to have an indeterminate value. So, after this declaration, b
has an indeterminate value. The const
is irrelevant; it means the source code of the program is not supposed to change b
, but it cannot remedy the fact that b
does not have a determined value.
Since the C standard permits any value to be used in each instance, onlinegdb.com conforms when it prints zero, and WSL conforms when it prints other values. Any int
values printed for printf("%d %d\n", a, b);
conform to the C standard.
Further, another provision in the C standard actually renders the entire behavior of the program undefined. C 2018 6.3.2.1 2 says:
… If the lvalue designates an object of automatic storage duration that could have been declared with the register
storage class (never had its address taken), and that object is uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined.
This applies to a
: It could have been declared register
because its address is never taken, and it is not initialized or assigned a value. So, using a
has undefined behavior, and that extends to the entire behavior of the program on the code branch where a
is used, which is the entire program execution.