Early in the history of C, compilers were written by different people for different environments using their own notions of how they wanted the language to behave, and the language developed organically rather than by design. When the C committee wrote the C standard, it allowed for varying behaviors in existing C implementations. In consequence, the semantics of declarations are somewhat complicated.
Outside of any function, int c;
is a declaration, not a definition. It is a special kind of declaration called a tentative definition, but, in spite of that name, it is not actually a definition. A declaration of an identifier for an object that is not a definition only tells the compiler about the identifier and the object; it does not cause space to be reserved for the object. Since it is only a declaration, it may be repeated multiple times. This simply repeats the information to the compiler without defining the object.
Inside a function, int c;
is a definition. It causes space to be reserved for the object. Since it is a definition, it should not be repeated. Again, the reasons for this are due to the history of the development of C, not due to planned design.
I suspect part of the reason things developed in this way is that multiple header files that wanted to use an external variable would declare it, as with int errno;
, and, once this practice had developed, compilers had to allow it. A program would typically include multiple headers, and sometimes multiple headers would declare the same identifier, intending to use the same object as other headers. In contrast, inside a function, we do not typically include headers. All the code for a function is usually written at one point in one file, and so we do not get multiple declarations like int i;
coming from different places. So, inside a function, int i;
can be made a regular definition.
A tentative definition will cause a definition to be created if, at the end of the translation unit (the source file being compiled, along with everything it includes), there is no definition for the identifier.