edits: 01/25/2008; 09/17/2008


Puzzles E21 ... E30

Linkage

The scope of an identifier is concerned with what the compiler can see. For example, when the compiler converts the following into machine language,

sum = alpha + beta;

it needs to know which variables sum, alpha and beta are referred to. Several different entities in a single source file might use these names, and scope is used to keep them neatly separated.

The linkage of an identifier is concerned with what the linker does with various entities (variables and functions) that have already been compiled. The output of the compiler is an object file. Each object file is created from just one source file. The linker creates an executable file out of several object files and library files.

An object file (or library file) contains functions and external variables that are in a form that is close to machine language. These entities are identified by name so other parts of the program can use them.

An entity in an object file uses the same identifier as its declaration in a source file. For example, the function foo() might be defined in a source file. In the corresponding object file there will be a section of machine language called foo. Several other source files might call the function foo(). Their object files will refer to foo()by name.

When does the same identifier in several object files correspond to just one entity and when does it correspond to several different entities? The linkage of the identifiers resolves this. Study the following picture

Compiling and Linking

The identifier x is used in three different source files. The source files are compiled into three object files. The object files are linked into one executable file. Source files in a project need to refer to entities defined in other source files. In the picture, fileA.c and fileC.c both refer to a single entity x. The x in fileB.c is a local variable and is a different entity.

Object files contain information about their entities, including their identifiers. When an entity (such as a variable) is external, the linker ensures that there is only one of that entity in the executable file. In the picture, variable x in fileA.c and fileC.c is external. Even though two object files refer to it, the linker ensures that there is just one x in the executable.

The picture shows the executable with a single int variable x (as a little box of memory) and the functions foo() and main() all linked together. The executable file does not contain the names of entities, although they are shown in the picture. An executable file is nearly pure machine code and data, although usually some debugging information is also included.


Puzzle E21

To show linkage in action, you must create a project that consists of several files. Here are three files:


/* --- fileA.c --- */ int x = 8;
/* --- fileB.c --- */ foo() { int x; x = 99; }
/* --- fileC.c --- */ int x; main() { foo(); printf("%d\n", x ); system("pause"); }

In Unix systems, compiling and linking is easily done from the command window. Assuming that the three files are in the same directory, which is currently the default directory, the three files can be compiled and linked by the following:

% cc fileC.c fileA.c fileB.c

The command "cc" invokes the compiler on the three source files, and then invokes the linker on the resulting three object files. The linker then creates the executable file a.out in the default directory. To execute it, do this:

% a.out

In program development systems such as Dev-C++, file creation, editing, compiling, linking, and execution are all done from inside the development system. In Dev-C++, create a new project, create each of the above files and add each to the project, then "compile and run" the project. This compiles the source files into object files, links them into an executable, and runs the executable. (For details, see the Dev-C++ documentation under its "Help" menu.)

Question: What does the above project write to the monitor when it is compiled, linked, and executed?


Linkage Rules

Linkage determines how multiple occurrences of the same identifier refer to the same or different entities. There are three kinds of linkage: no linkage, external linkage, and internal linkage.

1. No Linkage:

1.1 Each declaration of an identifier with no linkage denotes a unique entity. If there are several entities in the project with the same name and no linkage, scope determines which one a statement refers to.

1.2 The following have no linkage:

  1. an identifier declared to be anything other than a variable or a function,
  2. a function parameter,
  3. a identifier declared inside a block (and not explicitly declared external.)

2. External Linkage:

2.1 Several source files and libraries may declare a particular identifier with external linkage. Each declaration of that particular identifier denotes the same entity. It is the job of the linker to ensure that there is just one entity for that identifier in the executable file.

2.2 A variable declared outside of any function has external linkage unless otherwise specified (x in the previous puzzle has external linkage). Sometimes variables declared like this are called global variables.

2.3 A function name has external linkage unless otherwise specified (see foo and main, above.)

2.4 The keyword extern gives external linkage to an identifier and gives access to an entity defined in another file. If an identifier would already have external linkage, declaring it extern does not affect it.

3. Internal Linkage:

3.1 An identifier that has internal linkage is unique within its source file, but is invisible to other source files. If other source files use this same identifier, they refer to other entities.

3.2 The keyword static gives internal linkage to an identifier that otherwise would have external linkage. (This is the only way to get internal linkage.)


Puzzle E22 — Rule 1.2c, 2.1, and 2.4

What does the following code write to the monitor?


/* --- fileA.c --- */ int x = 8;
/* --- fileB.c --- */ foo() { int x; x = 99; }
/* --- fileC.c --- */ extern int x; main() { foo(); printf("%d\n", x ); system("pause"); }

Notice that this is nearly the same as the previous puzzle except now the keyword extern is used in fileC.c.


Puzzle E23 — Rule 2.1 and 2.4

What does the following code write to the monitor?


/* --- fileA.c --- */ int x = 8;
/* --- fileB.c --- */ foo() { extern int x; x = 99; }
/* --- fileC.c --- */ extern int x; main() { foo(); printf("%d\n", x ); system("pause"); }

Notice that the keyword extern is used in two of declarations of x How many entities x are there?


Puzzle E24 — Rule 2.1, 2.2, and 2.4

What does the following code write to the monitor?


/* --- fileA.c --- */ int x = 8;
/* --- fileB.c --- */ foo() { extern int x; x = 99; }
/* --- fileC.c --- */ int x; main() { foo(); printf("%d\n", x ); system("pause"); }

Note that extern has been removed from one of the declarations.


Puzzle E25 — Rule 2.1

Will the following code compile? If so, what does it write to the monitor?


/* --- fileA.c --- */ int x = 8;
/* --- fileB.c --- */ foo() { extern int x; x = 99; }
/* --- fileC.c --- */ int x = 77; main() { foo(); printf("%d\n", x ); system("pause"); }

This program is a slight variation of the previous one. Pay attention to the identifier x.


Puzzle E26

What does the following project write to the monitor?


/* --- fileB.c --- */ int x = 444 ; foo() { int x; x = 99; }
/* --- fileC.c --- */ int x ; main() { printf("x before foo: %d\n", x ); foo(); printf("x after foo: %d\n", x ); system("pause"); }

Pay attention to how many entities x there are, and what happens to them.


Puzzle E27 — Rule 1.2b and 2.4

What does the following write to the monitor?


/* --- fileB.c --- */ int x = 444 ; foo(int x) { printf("x as parameter: %d\n", x ); x = 25; printf("x as parameter: %d\n", x ); }
/* --- fileC.c --- */ main() { extern int x ; printf("x before foo: %d\n", x ); foo( 7 ); printf("x after foo: %d\n", x ); system("pause"); }


Puzzle E28 — Rule 3.1 and 3.2

What does the following write to the monitor?


/* --- fileA.c --- */ int x = 8;
/* --- fileB.c --- */ static int x = 444 ; foo() { printf("x in fileB: %d\n", x ); x = 25; printf("x in fileB: %d\n", x ); }
/* --- fileC.c --- */ extern int x ; main() { printf("x before foo: %d\n", x ); foo(); printf("x after foo: %d\n", x ); system("pause"); }

As usual, pay attention to how many x's there are and where they are visible.


Puzzle E29 — Rule 1.2b, 2.2, and 3.2

What does the following write to the monitor?


/* --- fileA.c --- */ int x = 8;
/* --- fileB.c --- */ static int x = 444 ; foo( int x ) { printf("parameter x: %d\n", x ); x = 25; printf("parameter x: %d\n", x ); }
/* --- fileC.c --- */ extern int x ; main() { printf("x before foo: %d\n", x ); foo( 999 ); printf("x after foo: %d\n", x ); system("pause"); }

All three linkage types are found in this project.


Puzzle E30

What does the following write to the monitor?


/* --- fileA.c --- */ int x = 8;
/* --- fileB.c --- */ static int x = 10 ; foo( ) { printf("x in foo: %d\n", x ); x = x+10 ; printf("x in foo: %d\n", x ); } bar( ) { printf("x in bar: %d\n", x ); x = 2*x ; printf("x in bar: %d\n", x ); }
/* --- fileC.c --- */ static int x = 999; main() { printf("x in main: %d\n", x ); foo(); bar(); printf("x in main: %d\n", x ); system("pause"); }

How many entities are named x?


— Return to the main contents page