The Foreword to the C99 standard itself mentions "mixed declarations and code" as one of the changes from C90. This was IMHO a poor choice of words, since it's not at all clear what "code" means. It can easily refer to everything that can appear in a C source file.
The actual change that was made by C99 was to permit mixing of declarations and statements within a block. The distinction between a declaration and a statement is unambiguously defined by the language syntax.
The line from one of your examples:
int y = time(NULL);
is a declaration, not a statement, even though it results in the execution of some code at run time. The presence or absence of an initializer, and whether that initializer is a constant expression or not, does not affect whether something is considered to be a declaration.
All four of the examples in your question are valid in C89/C90, in C99, and in C11. In each case, the block contains just declarations, no statements.
If you want to mix declarations and statements in C90, you do so by introducing nested blocks:
void func(void) {
int x = 1; /* a declaration */
x = 2; /* a statement; no declarations may follow in C90 */
{
int y = 3; /* a declaration */
y = 4; /* a statement */
}
}
The inner block it itself a statement. Because it's a statement, it can appear in that context. Because it's a compound statement, it can itself contain a sequence of declarations followed by a sequence of statements.
Even in C99 or C11, it can be advantageous to introduce nested blocks like this. The scope and lifetime of y
end at the closing }
of the block that contains its declaration. Restricting the scope of a declaration can make code easier to understand.
(A bit of background: C89 was the standard released by ANSI in 1989. ISO adopted it, with some changes in the document but not in the language it describes, as C90. ISO published an updated standard, C99, which was then adopted by ISO. ISO published another updated standard, C11, which was also adopted by ANSI. According to both ANSI and ISO, the 2011 standard is the current one, and all earlier editions are obsolete. But for historical reasons, the phrase "ANSI C" usually refers to the language described by the 1989 and 1990 editions. I usually try to avoid the phrase "ANSI C", referring instead to "ISO C", plus the publication year if it's relevant.)