0% found this document useful (0 votes)
39 views20 pages

Compiler C++

The document outlines the workings of C++, detailing the compilation process which includes preprocessing, compiling, and linking. It explains the differences between static and dynamic libraries, and emphasizes the importance of efficient coding in telecommunications. The document also highlights the role of preprocessor directives and the significance of avoiding duplicate definitions in code.

Uploaded by

Majito jungle
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
39 views20 pages

Compiler C++

The document outlines the workings of C++, detailing the compilation process which includes preprocessing, compiling, and linking. It explains the differences between static and dynamic libraries, and emphasizes the importance of efficient coding in telecommunications. The document also highlights the role of preprocessor directives and the significance of avoiding duplicate definitions in code.

Uploaded by

Majito jungle
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 20

How does C++ work?

Programming for Telecommunications


Filippo Campagnaro
Programming for TLC

[email protected]
Outline
1. Why C++?

2. Compilations steps

3. Preprocessor

4. Compiler
Programming for TLC

5. Linker

6. Static library vs dynamic library


MORE INFO: “Advanced C and C++ Compiling”, Milan Stevanovic
http://www.keil.com/support/man/docs/armcc/armcc_chr1359124221739.htm
Why C++, if I’ve learnt Java!
• Java works over a Virtual Machine: your software is
“compiled” for the virtual machine, whose interpreter
“translates” the instructions for the VM to the instructions
for the actual hardware architecture.
• In C++ you must compile in machine code for the target
machine for which the code has to be executed, using the
proper tool-chain (arm, x86, x64, etc.)
• Way faster: the code is directly executed to the machine!
Programming for TLC

• Pay attention: bad programming in C++ may result in slow software


• Drawback: if your software needs to run in different target
machines, you need to cross compile it for each target
• In TLC you must be fast (e.g., in a Gbps router, the routing
software can’t be the bottleneck!) 3
How C++ works
Libraries

preprocessor Translation compiler


Source file Object file
unit

linker Executable

preprocessor Translation compiler


Source file Object file
unit

• Preprocessing: the preprocessor takes a C++ source code file and


Programming for TLC

deals with the #includes, #defines and other preprocessor


directives. The output of this step is a "pure" C++ file without pre-
processor directives, the translation unit.
• Compilation: the compiler takes the translation units and
produces an object file from each of them.
• Linking: the linker takes the object files produced by the
compiler and produces either a library or an executable file. 4
Preprocessor: always before compiler
• Evaluates the preprocessor directives, aka whatever is written
after #, and substitutes them into the code. Agnostic to C++
syntax.
• E.g.: macros  use them as less as possible (here use constexpr!)
CPP FILE
#define MAX_HGHT 720 TRANSLATION UNIT
#define AREA(a,b) (a*b)
int maxArea(int a) int maxArea(int a)
{ {
return return
PREPROCESSOR
AREA(a,MAX_HGHT); a*720;
} }
int main(int argc, int main(int argc,
Preprocessor

char* argv[]) char* argv[])


{ {
int l = MAX_HGHT; int l = 720;
int a = maxArea(l); int a = maxArea(l);
} } 5
Preprocessor: #include
//my-fun.h //example.h
inline int incr(int i) #include “my-fun.h”
{ inline int ex(int i)
return i+1; {
} return incr(i+1);
}
//example2.h
#include “my-fun.h” //example.cpp
inline int ex2(int i) #include <iostream>
{ #include “example.h”
return incr(i+2); #include “example2.h”
} int main()
{
DOES NOT std::cout << ex(1)
Preprocessor

<< ex2(2);
COMPILE! }

error: redefinition of ‘int incr(int)’ 6


Why is it not compiling?
error: redefinition of ‘int incr(int)’
// ONLY CPP FILES ARE COMPILED: NOT HEADERS!!
// THE COMPILER SEES a unique file (translation unit)
... //code of lines of iostream
inline int incr(int i) {
return i+;
}
inline int ex(int i) { example.h
return incr(i+1);
}
inline int incr(int i) {
return i+;
}
inline int ex2(int i) {
example2.h
Preprocessor

return incr(i+2);
}
int main() {
std::cout << ex(1) << ex2(2); 7
}
Preprocessor: Conditional compilation
//my-fun.h
#ifndef MY_FUN_H If MY_FUN_H has already
#define MY_FUN_H been defined, do not
inline int incr(int i) compile this code
{
return i+1;
}
#endif
• This construct is the wrapper #ifndef or “include guards”
• When the header is included again, the conditional will be false, and
the preprocessor will skip over the entire contents of the file, and the
compiler will not see it twice.
Preprocessor

• Always use it in all your .h files: you never know if you need to include
them somewhere in the future!!
• Be sure all headers are defined with a different name, or you’ll have
big troubles!!! 8
Now it compiles..
// ONLY CPP FILES ARE COMPILED: NOT HEADERS!!
// THE COMPILER SEES a unique translation unit
// (basically, one per cpp file)

... //code of lines of iostream


inline int incr(int i) {
return i+1;
} example.h
inline int ex(int i) {
return incr(i+1);
}

inline int ex2(int i) {


example2.h
Preprocessor

return incr(i+2);
}
int main() {
std::cout << ex(1) << ex2(2);
} 9
Compiler
• Parses (linguistic analysis) the translation unit
• Converts it to assembly code (still human readable ASCII) for a specific
CPU instruction set
• Optimizes the assembly code: the use of the registers is minimized, and
eliminates the parts of the code that do not need to be executed.
Different levels of optimization:
• O0 (Minimum optimizer) doesn’t optimize: fast compilation, slow code, used
for debugging
• O1 (Restricter optimizer) just removes unused lines, used for debugging
• 02 (High optimization, DEFAULT) minimizes the use of register, harder to
debug
• 03 (Maximum optimization) optimizes more, poor debug view
• Converts the assembly code into the specific machine instructions
producing the actual binary: the object file.
Compiler

• The compilation step is performed on each translation unit: each


translation unit is compiled into a binary object file
10
Compiler
• The object file contains the compiled code (in binary form)
of the symbols found in the translation unit.
• Object files can refer to symbols that are not defined (but
just declared).
• You can compile each translation unit separately, so you
don't need to recompile everything if you only change a
single file.
• The object files can be put in archives called static
libraries.
• At this stage only compiler errors, like syntax errors (during
the Linguistic analysis phase) or failed overload resolution
errors, are reported.
Compiler

• Code is still not ready to be executed!


11
Compiler
//my-fun.h //example.h
int incr(int i); #include “my-fun.h”
inline int ex(int i)
{
The compiler }
return incr(i+1);

CREATES example.o //example.cpp


from example.cpp, #include <iostream>
#include “example.h”
but doesn’t produce int main()
{
executable: a linker std::cout << ex(1);
error arises: }
Compiler

undefined reference to `incr(int)'


collect2: error: ld returned 1 exit status 12
Compiler
//example.h
//my-fun.h #include “my-fun.h”
int incr(int i); inline int ex(int i){
return incr(i+1);
//my-fun.cpp }
#include “my-fun.h”
int incr(int i) //example.cpp
{ #include <iostream>
return i+1; #include “example.h”
} int main() {
std::cout << ex(1);
}
It creates the executable:
-my-fun.cpp compiled into my-fun.o
-example.cpp compiled into example.o,
Compiler

-Linker creates the executable, resolving the


undefined symbol incr into example.o 13
Linker
• The linker produces the final compilation output from
the object files the compiler produced. This output can
be either a shared (or dynamic) library or an executable.
• It links all the object files by replacing the references to
undefined symbols with the correct addresses.
• Each of these symbols can be defined in other object
files or in libraries.
• If they are defined in libraries other than the standard
library, you need to tell the linker about them
• The most common errors are missing definitions (not
exists or the file not provided to the linker) or duplicate
definitions.
Linker

14
Linker vs compiler duplicated definitions
• Duplicated definitions in a single translation unit =
compiler error error: redefinition of ‘int incr(int)’
• Duplicated definition in two different translation units =
linker error
//my-fun.h //example.cpp
int incr(int i); #include “my-fun.h”
int incr(int i) {
//my-fun.cpp return i+1;
#include “my-fun.h” }
int incr(int i) { int main() {
return i+1; std::cout << incr(1);
} }
my-fun.cpp:3: multiple definition of `incr(int)'
example.cpp:3: first defined here
Linker

collect2: error: ld returned 1 exit status


15
Wrapping it up: 1 - Preprocessor
//my-fun.h //example.h
int incr(int i); #include “my-fun.h”
inline int ex(int i){
//my-fun.cpp return incr(i+1);
#include “my-fun.h” }
int incr(int i)
{ //example.cpp
return i+1; #include “example.h”
} int main() {
int i = ex(1) + ex(2);
translation }
unit translation unit

//translation unit int incr(int i);


//of my-fun.cpp inline int ex(int i){
int incr(int i); return incr(i+1);
Summarize

int incr(int i) }
{ int main() {
return i+1; int i = ex(1) + ex(2);
} }
16
Wrapping it up: 2 - Compiler
//translation unit //translation unit
//of my-fun.cpp //of example.cpp
int incr(int i); int incr(int i);
inline int ex(int i){
int incr(int i) return incr(i+1);
{ }
return i+1; int main() {
} int i = ex(1) + ex(2);
}

compilation compilation

my-fun.o example.o
Summarize

17
Wrapping it up: 3 - Linker
my-fun.o example.o
definition of
int incr(int)

executable_example
Summarize

18
Static library
• It is an archive of object files created at compile time
• The executable is portable, but very large
• If one file is changed, the whole system needs to be recompiled

objects Static library


archiver
lib1.a
obj1.o obj2.o obj3.o

Project 1 Project 2

obj4.o obj5.o obj1.o obj2.o obj3.o obj1.o obj2.o obj3.o obj6.o obj7.o
Libraries

linker linker
executable executable 19
Shared (or Dynamic) library
• Library created by the linker, it can depend on external libs,
• In this case the linker trusts the fact it will be able to link them in run time
• Loaded at runtime during the code execution, once for all programs
• If one file is changed, only the library needs to be recompiled
objects Shared
linker
Library
lib1.so Loader at
objects RUNTIME
linker Shared Dynamic
Library linking
lib2.so

objects
Libraries

linker
Executable
20

You might also like