First | Next | Previous | Last | Glossary | About |
//ex18.cc #include <iostream> int i = 99; /* an external or global declaration */ void junk(void); int main () { int i = 1, j = 1; // these are available within this block // unless redefined in an enclosed block cout << "main block i is " << i << " and j is " << j << endl; { /* this is an enclosed block,i is redefined, j isn't */ /* it isn't a good idea to do this sort of thing */ int i = 2; j = i << 4; cout << "second block i is " << i << " and j is " << j << endl; } /* end of enclosed block */ cout << "main block i is " << i << " and j is " << j << endl; junk(); return 0; } /* this is the end of the main block */ void junk(void) { cout << "which i is this? " << i << endl; } /* another block */ |
In C++ a block is a set of statements enclosed in braces {block} or the code contained within a file. In the example here the total program is a block and it encloses other blocks. For example the block for the main() function starts with it's opening brace and finishes with that block's closing brace.
An identifier is available within a block unless it is redefined in an enclosed block.
//exscope1.cc #include <iostream> void show_x(); void main() { int x = 20; show_x(); } void show_x() { cout << x; } |
The scope of a name (an identifier) is the part of the program over which the name is defined. In others words it is that part of a program over which the identifier can be seen by other identifiers and used by other identifiers. For example:
If you compile exscope1.cc you will get an error:
exscope1.cc: In function `void show_x()': exscope1.cc:11: `x' undeclared (first use this function) exscope1.cc:11: (Each undeclared identifier is reported only once exscope1.cc:11: for each function it appears in.)
The reason for the error is that variables declared within a function are private or local to that function. The variable x declared in function main() is local to main. It is a private variable and function show_x() simply can't see it.
//exscope2.cc #include <iostream> void show_x(); int x = 20; void main() { cout << x; show_x(); } void show_x() { cout << x; } |
If the variable x is moved to a global position then it is available to other functions. Now, since x is outside any of the functions it is visible to everything.
//exscope3.cc #include <iostream> void show_x(); int x = 20; //global x void main() { int x = 10; //local x cout << x; show_x(); } void show_x() { cout << x; } |
An identifier can be made "invisible" by another identifier of the same name declared at a lower level in the program. In this example you can see that the global x is "replaced" by the local x in main() but not in show_x(). The x referred to by main() is the local x. The x referred to by show_x() is the global x.
//exscope4.cc #include <iostream> void show_x(); void main() { cout << x; show_x(); } int x = 20; //this is a global //but is only available //from this point on. void show_x() { cout << x; } |
There is another aspect to scope that you should be aware of. The position of an identifier within a block is also a factor in determining scope. If you compile this program you will get the error message exscope4.cc:6: `x' undeclared (first use this function) or something like it. The reference to x in main() is a reference to a variable that cannot be seen. This is because x, even though it is declared at a global level, is not declared until after main().
With regards to scope the question to ask is "Can the user of the identifier see the identifier?".
int fred() { int x, y; } |
In the function fred the variables x and y are local or private variables, they can't be accessed by another function since they won't be visible to another function. Usually local variables only exist during the execution of the function and each time the function is called the variables will need to be initialised before use. Variables like this are known as automatic variables. You normally don't declare local variables as automatic since they are "automatically" automatic.
Variables can be declared as global variables, available to everything, these are also known as external variables. External variables are defined outside of any functions and retain their values during the course of a program. If a function uses an external variable and the external variable is declared in the same source file as the function using it and before the function then no further declaration is required. But, if the external variable is declared in a different source file then any function which uses it must also declare the variable, as an external variable, e.g.
file1.cc |
int ext_x; // declare the variable |
file2.cc |
#include <iostream> #include "file1.cc" void func_x() { extern int ext_x; // declare variable // so that the function // knows that it is // external to the // block ext_x = 21; cout << "In function func_x() " << ext_x << endl; } |
file3.cc |
#include "file2.cc" int main() { extern int ext_x; func_x(); cout << "In function main() " << ext_x << endl; return 0; } |
Even though the external variable ext_x is declared three times it only has memory allocated to it once.
Automatic and external variables are both storage specifiers. A third specifier is the static specification.
//ex19.cc #include <iostream> // All of these (ext1, ext2, ext3, addupstatic, adduptstat2, // addupauto) are external or global or (sometimes called) // public symbols. int ext1 = 10, ext2 = 12; int ext3(void); int addupstatic(void); int addupstat2(void); int addupauto(void); int main () { int x = 1,y = 2; // these are local or automatic variables cout << "\nexternal auto " << ext1 << " " << ext2 << " " << x << " " << y << endl; cout << "function with external " << ext3() << endl; cout << "static variables 1 ->"; for (x = 0; x < 10; x++) cout << " " << addupstatic(); cout << endl; cout << "static variables 2 ->"; for (x = 0; x < 10; x++) cout << " " << addupstat2(); cout << endl; cout << "auto variables ->"; for (x = 0; x < 10; x++) cout << " " << addupauto(); cout << endl; return 0; } int ext3(void) { return ext1 * ext2; } int addupstatic(void) // static vars are initialised at start up { static int x,y; // and retain their values. x += 1; y += 1; return x + y; } int addupauto(void) // auto vars are not initialised at startup { int x = 1, y = 1; // but each time they are called and do not // retain their values. x += 1; y += 1; return x + y; } int addupstat2(void) // static vars can be initialised to some { static int x = 4,y = 4; // value other than 0 but will only be // initialised at the first call. x += 1; y += 1; return x + y; } |
Example 19 shows the different kinds of storage specifications. You should study this example closely.
I mentioned earlier that an automatic variable inside a function doesn't exist until the function is called. At that time the memory for the automatic variable is allocated dynamically from a memory stack and released when the function is finished. Static storage comes from a different memory allocation - it is allocated from a static area of memory so static variables within functions can retain their values between calls to the functions.
There isn't much to do as a tutorial for this topic apart from compiling and running the sample programs. Although storage specification is an important topic it is perhaps a bit early to look at it in any significant detail.
First | Next | Previous | Last | Glossary | About |
Copyright © 1999 - 2001 David Beech