Scopes and Files

In C, program code is divided into areas using curly brackets {}. These areas are referred to as scopes. Scopes basically define how statements and symbols belong together and are used in various elements of the C language. Scopes can be nested within each other, with the outermost scope being delimited by the implementation file and referred to as the global scope.

begin file
begin global scope


begin function scope

begin while scope


end while scope

end function scope
end global scope
end of file


#include <stdio.h>

int main(){ 
  int a = 5;
  while(a > 0){ 
    printf("%d\n", a);
    a--;
  }
  return 0;
}

Details

Scopes are always enclosed by curly brackets {} and every scope can contain any number of scopes in turn. Scopes can thus be nested within one another, whereby the curly brackets must be well-formed (each closing bracket must be introduced by a unique opening bracket). In order to better highlight scopes visually, program code within a scope is ually indented by one tab step.

Scopes have two main functions: Structuring code and determining the visibility of symbols.

Code Structuring

One task of scopes is to divide program code into executable code blocks: The statements contained in curly brackets are considered to belong together. Basically, a scope can be defined by simply using opening and closing curly brackets in the middle of the program text. However, that is rarely used in this raw form. Much more often, this method is used in connection with control structures. By specifying a scope in a control structure, the compiler considers all statements within the scope to belong together which then is called a statement block.

When defining a function, the curly brackets are also used to specify that any program code that is inside the function scope belongs to that function.

Symbols

The second (and far more important) purpose of scopes is to control the visibility of symbols across different scopes.

Basically, the following applies to a scope: All symbols that are declared or defined within a scope are invisible to program code that is outside the scope. However, program code that is inside a scope can access symbols outside of the scope. These rules also apply when having nested scopes: Nothing is visible from outside to inside, everything is visible from inside to outside.

A symbol may only be defined once within a scope. Symbol names in other scopes (outside, as well as inside) are not considered. If multiple symbols with the same name exist spanning several nested scope boundaries, only the one symbol which is the innermost relative to the current scope is referenced during execution. Therefore, if there exists a symbol with the same name in an outer scope, that symbol can not be addressed in C. This is called shadowing.

More information about symbols inside scopes can be found on the statement blocks page.

Files: The global scope

Program code in C is written in plain text files. These files are referred to as source files. A basic distinction is made between implementation files and header files. Today's development environments automatically accept any implementation file as a starting point for the compiler. The header files are not addressed directly by the compiler but are integrated into the implementation file by using the #include preprocessor directive.

Header files usually have the file extension .h and mainly contain declarations. In certain cases, definitions can also be found within header files, for example when using inline functions.

Implementation files in C have the file extension .c and contain mainly definitions. By including header files, additional functionality can be accessed, the implementation of which may be located in other c files or even in precompiled object files such as libraries. More information can be found on the linker page.

For each implementation file, the compiler initially assumes the global scope. Correctly, this scope is called file-scope. Here on ManderC, the term global scope is used instead. All symbols declared or defined in this non-{}-bracketed scope are global symbols and can be referenced anywhere. The main-function also is always located in the global scope. The file that contains the main function is called the primary source file.

In principle, no executable program code may be located in the global scope but must always be inside of a function scope. Initializations of global variables though are allowed. In C however, these are restricted to constant values.

In modern programming, global symbols are considered bad coding style, but they are not forbidden. They are still used by programmers when, for example, a small program has to be written that is more geared towards functionality than well thought-out structuring (quick and dirty). It should also be noted that compilers and linkers themselves sometimes implicitly define global variables, which often times is what makes an executable execute-able in the first place (see runtime system).

Next Chapter: Code-Style-Guides and Code Analyzers