Variable declaration placement in C

I long thought that in C, all variables had to be declared at the beginning of the function. I know that in C99, the rules are the same as in C++, but what are the variable declaration placement rules for C89/ANSI C?

The following code compiles successfully with gcc -std=c89 and gcc -ansi:

#include <stdio.h>
int main() {
    int i;
    for (i = 0; i < 10; i++) {
        char c = (i % 95) + 32;
        printf("%i: %c\n", i, c);
        char *s;
        s = "some string";
        puts(s);
    }
    return 0;
}

Shouldn't the declarations of c and s cause an error in C89/ANSI mode?


It compiles successfully because GCC allows the declaration of s as a GNU extension, even though it's not part of the C89 or ANSI standard. If you want to adhere strictly to those standards, you must pass the -pedantic flag.

The declaration of c at the start of a { } block is part of the C89 standard; the block doesn't have to be a function.


For C89, you must declare all of your variables at the beginning of a scope block.

So, your char c declaration is valid as it is at the top of the for loop scope block. But, the char *s declaration should be an error.


Grouping variable declarations at the top of the block is a legacy likely due to limitations of old, primitive C compilers. All modern languages recommend and sometimes even enforce the declaration of local variables at the latest point: where they're first initialized. Because this gets rid of the risk of using a random value by mistake. Separating declaration and initialization also prevents you from using "const" (or "final") when you could.

C++ unfortunately keeps accepting the old, top declaration way for backward compatibility with C (one C compatibility drag out of many others...) But C++ tries to move away from it:

  • The design of C++ references does not even allow such top of the block grouping.
  • If you separate declaration and initialization of a C++ local object then you pay the cost of an extra constructor for nothing. If the no-arg constructor does not exist then again you are not even allowed to separate both!

C99 starts to move C in this same direction.

If you are worried of not finding where local variables are declared then it means you have a much bigger problem: the enclosing block is too long and should be split.

https://wiki.sei.cmu.edu/confluence/display/c/DCL19-C.+Minimize+the+scope+of+variables+and+functions