Table of Contents
In Java, accessing fields and methods in an object can be controlled using three scopes: public, private and protected. The C language has much simpler rules to control what is known as the “scope of validity” of a variable.
The “scope of validity” of a variable is composed of those code portions where its content can be accessed and manipulated. These portions typically correspond with different code blocks surrounded by curly braces (“{}”). For example, when a function invokes another function, a new scope (the invoked function) is created inside another one (the calling function) and disappears upon termination. There are certain variables with intuitive scopes of validity, as for example, the variables defined at the top of a function body. But C allows these scopes to be modified by using declaration prefixes.
Every variable declared outside of the functions as a global scope, that is, it can be accessed from any point in the program. The following code shows an example of this situation.
1 2 3 4 5 6 7 8 9 10 11 12 13 | int number; int function() { number++; return number; } int main(int argc, char *argv[]) { number = 0; function(); return 0; } |
Variable number
is declared in line 1,
outside a function, therefore it is global. Next, the variable is accessed
in lines 4 and 10.
But in order to access correctly a global variable, there
are two requirements to fulfill derived from the way the compiler
processes the files. If the variable is declared in the same file, its
declaration must precede its use (the compiler reads each file in one
pass). If the variable is declared in another file, the same exact
definition must be included in the file but with the prefix
“extern
” (the compiler only remembers
information in the file that is processing).
File 1 | File 2 | ||||
---|---|---|---|---|---|
|
|
Variable number
is defined as global in line
1 of file 1. To access it from file 2, the declaration (without
initialization) is replicated in line 1 of file 2 adding the
“extern
” prefix. The global variable is accessed
in line 4 of file 2. If the first line of this file is omitted, the
compiler emits an error that the variable number
has not been
declared. If in file 2 the declaration is included without the
“extern
”, the compiler emits the error that a
variable has been multiply defined.
Copy and paste the content of the two files in the
example in file file1.c
and
file2.c
. Compile with the command gcc
-Wall -o program file1.c file2.c. Check that the executable
with name program
is created and execute it with
the command ./program. It should print no
message. Make changes in the declaration to check the rules imposed by
the compiler.
Any variable declaration may have the prefix
“static
”. Static variables in C have the
following two properties:
They cannot be accessed from any other file. Thus,
prefixes “extern
” and
“static
” cannot be used in the same
declaration.
They maintain their value throughout the execution of the program independently of the scope in which they are defined.
As a consequence of these two properties, the following two cases are derived:
If a static variable is defined outside of the functions it will be accessible only by the code that follows in the file it is declared.
If the static variable is declared in a function, it will only be accessible from the function, and it will keep its value between function executions.
This behavior is counter intuitive because this variables are declared with the rest of variables in a function, but while the latter acquire new values with each execution, the static variables preserve these values between executions.
The following program shows an example of the behavior of a static variable defined in a function.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #include <stdio.h> int function() { static int number = 10; /* Static variable */ number++; /* Maintains the value of the previous execution */ return number; } int main() { /* Prints the result of two invocations to function */ printf("%d\n", function()); /* Prints 11 */ printf("%d\n", function()); /* Prints 12! */ return 0; } |
Line 4 declares the static variable number
and assigns the value 10. Thus, the first time the function is executed,
the variable has this value and is increased to 11. This is the value
printed when executing line 11. But the function is invoked again,
number
maintains its value and therefore is increased to 12,
which is the value printed when executing line 12 of the program.
Copy and paste the program in the previous example into a text file in your development environment. Compile it with the command gcc -o program file.c replacing file.c by the name given to the file. Execute the program with the command ./program and check that the result is as expected.
The following example shows the behavior of a static variable when defined outside a function.
File 1 | File 2 |
---|---|
/* Global variable */
int number = 10;
int main(int argc, char *argv[])
{
number++;
return 0;
}
/* Available only from this point in this file */
static int coefficient = 20;
void function2()
{
number++;
coefficient++;
}
|
extern int number;
/* Variable coefficient cannot
be accessed in this file */
int function()
{
number++;
return number;
}
|
The variable number
is declared globally and
may be accessed from other file when including its declaration with the
“extern
” prefix. However, the variable
coefficient
is only accessible from the file in which it is
declared and only from that point on (it is not visible in function
main
.
The problem of “shadowing” appears when a variable is defined in a scope with the same name of another one valid in a higher level scope. The following example shows this situation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #include <stdio.h> int number = 10; void function() { int number; /* Colission with global variable*/ number = 20; } int main(int argc, char *argv[]) { function(); /* Print the value of number */ printf("%d\n", number); /* Which value is printed? */ return 0; } |
The declarations in lines 2 and 5 are identical but they
are included in different scopes (global versus local to a function). The
compiler allows this declaration. But the shadowing appears when the
function is executed: the global variable number
cannot be
accessed because the name refers to the variable local to the
function. Upon function termination, the global variable is no longer
“shadowed” and is accessible again, and its value (10) is
printed in line 15.
Copy and paste this program in a text file in your development environment. Add more declarations, compile and execute the program to verify the shadowing policy of the compiler.