Thursday, April 25, 2013

Namespaces and Linkage demystified....

What is translation unit ?

A translation unit is the source code that gives rise to single object file. It is basically a single source file, plus all of its #include files. 

More elaboration on this. C++ code is compiled in two steps. In the first pass preprocessing is done. Preprocessing includes macro processing and bringing in the entire   file(s) included by #include directive.  The result of the first pass is called as translation unit. So, what programmer presents to compiler is  a 'source file' e.g. .cpp and what compiler sees is a translation unit. Translation unit plays very important role visibility and linkage.

Modularity - A design decision.

A program is composed of modules. Each module can be composed of following things. Modularities are of two types. Physical and Logical.
  • Namespaces
  • Classes
  • Templates
  • Design Patterns ( composed of above three )
  • Libraries ( STL, boost etc)
  • Processes, Threads ( OS, concepts), interprocess communication.
  • Shared memory, Pipes, mutex etc.
  • Files ( physical )
The files is the only physical way of achieving modularity, but for C++ , files are just means of organising the source code, and unfortunately we tend to think of modularity in terms of files, instead we should think modularity in terms of the other logical things.
Main aim of the the design decisions is to increase the modularity and decrease the dependency between the modules, that way design becomes clear, dependency reduces and program also compiles faster. Logical structure of program may not be same as that of physical structure across the files. e.g. namespaces are open and can span across multiple source files. But Logical structure should guide the physical structure of the program. Bottom line is we should think in terms of modules, translation units and logical modules only.

Modular compilation.

Compiler compiles each module rather translation unit separately in isolation from the rest of the program and linker then links all the modules together. It is programmers job to ensure that all the declaration required for each module to compile successfully should be consistent across the program as if all the modules are part of single source file. If this requirement is not satisfied, linker produces errors.


Linkage.

Now is the time to understand linkage....by examples.

//file1.cpp
int m = 1;         //definition
int y;               //definition ...means int y = 0;
int f() { //do something}   //function definition
void another(){//another function}
double duplicate; //OK

//file2.cpp
extern int m;    //declaration.
int y =2;
extern int z= 9; //definition; extern is ignored. any declaration with initialiser is definition.
int f();  //function declaration 
void g() { m = f(); } //function call.
another(); //function call , error: another is not declared here.
double duplicate;  //OK

Let us analyse this step by step.

  • m is defined in file.cpp and declared using extern keyword in file2.cpp, this is ok, extern indicates it is a declaration and the variable is defined in some other translation unit.
  • extern int z = 9; This is definition and NOT declaration. Remember any declaration with initialiser is definition. Here extern is ignored. 
  • The only exception to rule above is: variables defined without initialiser in either 
    • global scope OR
    • namespace scope . e.g. int y; in file1.cpp is definition and NOT declaration. i.e. global or namespace scoped variables are initialised by default.
    • This does not apply to local ( automatic) and objects created on free store.
  • Now there is error with variable y. It is defined twice. This is not allowed in C++. C++ follows one definition rule or ODR. More on this follows.
  • function call another() in file2.cpp is an error too. another() is not declared in file2.cpp
  • Finally definition double duplicate; is OK. This conforms to ODR more on this follows.

External Linkage:

Name that can be used in the translation units different from the one in which it was defined is said to have external linkage. All the names in the example above have external linkage. 

Internal Linkage:

A name that can be referred only in the translation unit in which it is defined is said to have internal linkage.



No comments: