Static Duration, Internal Linkage

Applying the static modifier to a file-scope variable gives it internal linkage. The difference between internal linkage and external linkage becomes meaningful in multifile programs. In that context, a variable with internal linkage is local to the file that contains it. But a regular external variable has external linkage, meaning that it can be used in different files, as the previous example showed.

What if you want to use the same name to denote different variables in different files? Can you just omit the extern?

// file1
int errors = 20;        // external declaration
...
---------------------------------------------
// file2
int errors = 5;        // ??known to file2 only??
void froobish()
{
      cout << errors;   // fails
      ...

No, this attempt fails because it violates the one definition rule. The file2 definition attempts to create an external variable, so the program winds up with two definitions of errors, which is an error.

But if a file declares a static external variable that has the same name as an ordinary external variable declared in another file, the static version is the one in scope for that file:

// file1
int errors = 20;        // external declaration
...
---------------------------------------------
// file2
static int errors = 5;  // known to file2 only
void froobish()
{
      cout << errors;   // uses errors defined in file2
      ...

This doesn’t violate the one definition rule because the keyword static establishes that the identifier errors has internal linkage, so no attempt is made to bring in an external definition.


Note

In a multifile program, you can define an external variable in one and only one file. All other files using that variable have to declare that variable with the extern keyword.


You can use an external variable to share data among different parts of a multifile program. You can use a static variable with internal linkage to share data among functions found in just one file. (Namespaces offer an alternative method for this.) Also if you make a file-scope variable static, you needn’t worry about its name conflicting with file-scope variables found in other files.

Listings 9.7 and 9.8 show how C++ handles variables with external and internal linkage. Listing 9.7 (twofile1.cpp) defines the external variables tom and dick and the static external variable harry. The main() function in that file displays the addresses of the three variables and then calls the remote_access() function, which is defined in a second file. Listing 9.8 (twofile2.cpp) shows that file. In addition to defining remote_access(), the file uses the extern keyword to share tom with the first file. Next, the file defines a static variable called dick. The static modifier makes this variable local to the file and overrides the global definition. Then the file defines an external variable called harry. It can do so without conflicting with the harry of the first file because the first harry has internal linkage only. Then the remote_access() function displays the addresses of these three variables so that you can compare them with the addresses of the corresponding variables in the first file. Remember that you need to compile both files and link them to get the complete program.

Listing 9.7. twofile1.cpp


// twofile1.cpp -- variables with external and internal linkage
#include <iostream>     // to be compiled with two file2.cpp
int tom = 3;            // external variable definition
int dick = 30;          // external variable definition
static int harry = 300; // static, internal linkage

// function prototype
void remote_access();

int main()
{
    using namespace std;
    cout << "main() reports the following addresses: ";
    cout << &tom << " = &tom, " << &dick << " = &dick, ";
    cout << &harry << " = &harry ";
    remote_access();
    return 0;
}


Listing 9.8. twofile2.cpp


// twofile2.cpp -- variables with internal and external linkage
#include <iostream>
extern int tom;         // tom defined elsewhere
static int dick = 10;   // overrides external dick
int harry = 200;        // external variable definition,
                        // no conflict with twofile1 harry

void remote_access()
{
    using namespace std;
    cout << "remote_access() reports the following addresses: ";
    cout << &tom << " = &tom, " << &dick << " = &dick, ";
    cout << &harry << " = &harry ";
}


Here is the output from the program produced by compiling Listings 9.7 and 9.8 together:

main() reports the following addresses:
0x0041a020 = &tom, 0x0041a024 = &dick, 0x0041a028 = &harry
remote_access() reports the following addresses:
0x0041a020 = &tom, 0x0041a450 = &dick, 0x0041a454 = &harry

As you can see from the addresses, both files use the same tom variable but different dick and harry variables. (The particular address values and formatting may be different on your system, but the tom addresses will match each other, and the dick and harry addresses won’t.)

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.188.201