Lesson Objectives
By the end of this chapter, you will be able:
- Explain the C++ compilation model
- Execute the main() function
- Illustrate the declaration and definition of variables
- Determine built-in arithmetic types, references, and pointers
- Explain the scope of a variable
- Use control flow statements
- Define and utilize arrays
In this chapter, you will learn about the usage of variables and control flow statements to create more robust programs.
Introduction
C++ has been a major player in the software development industry for more than 30 years, supporting some of the most successful companies in the world.
In recent years, interest in the language has been growing more than ever, and it is an extremely popular choice for large-scale systems, with many big companies sponsoring its advancement.
C++ remains a complex language, which puts a lot of power in the hands of the developer. However, this also comes with a lot of opportunities to make mistakes. It is a unique language as it has the ability to enable programmers to write high-level abstractions while retaining full control of hardware, performance, and maintainability.
The C++ Compilation Model
It is fundamental to know how C++ compilation works to understand how programs are compiled and executed. Compiling C++ source code into machine-readable code consists of the following four processes:
- Preprocessing the source code.
- Compiling the source code.
- Assembling the compiled file.
- Linking the object code file to create an executable file.
Let's start with a simple C++ program to understand how compilation happens.
Create a file named HelloUniverse.cpp and save it on the Desktop after copy-pasting the following code:
#include <iostream>
int main(){
// This is a single line comment
/* This is a multi-line
comment */
std::cout << "Hello Universe" << std::endl;
return 0;
}
Now, using the cd command on the Terminal, navigate to the location where our file is saved and execute the following command if you are on UNIX:
> g++ -o HelloUniverse HelloUniverse.cpp
> ./HelloUniverse
If you are on a Windows system, a different compiler must be used. The command to compile the code with the Visual Studio compiler is as follows:
> cl /EHsc HelloUniverse.cpp
> HelloUniverse.exe
This program, once executed, will print Hello Universe on the Terminal.
Let's demystify the C++ compilation process using the following diagram:
Figure 1.1: C++ compilation of the HelloUniverse file
- When the C++ preprocessor encounters the #include <file> directive, it replaces it with the content of the file creating an expanded source code file.
- Then, this expanded source code file is compiled into an assembly language for the platform.
- The assembler converts the file that's generated by the compiler into the object code file.
- This object code file is linked together with the object code files for any library functions to produce an executable file.
Difference Between Header and Source Files
Source files contain the actual implementation code. Source files typically have the extension .cpp, although other extensions such as .cc, .ccx, or .c++ are also quite common.
On the other hand, header files contain code that describes the functionalities that are available. These functionalities can be referred to and used by the executable code in the source files, allowing source files to know what functionality is defined in other source files. The most common extensions for header files are .hpp, .hxx, and .h.
To create an executable file from the header and the source files, the compiler starts by preprocessing the directives (preceded by a # sign and generally at the top of the files) that are contained in them. In the preceding HelloUniverse program, the directive would be #include. It is preprocessed by the compiler before actual compilation and replaced with the content of the iostream header, which describes standard functionality for reading and writing from streams.
The second step is to process each source file and produce an object file that contains the machine code relative to that source file. Finally, the compilers link all the object files into a single executable program.
We saw that the preprocessor converts the content of the directives into the source files. Headers can also include other headers, which will be expanded, creating a chain of expansions.
For example, let's assume that the content of the logger.hpp header is as follows:
// implementation of logger
Let's also assume that the content of the calculator.hpp header is as follows:
#include <logger.hpp>
// implementation of calculator
In the main.cpp file, we include both directives, as shown in the following code snippet:
#include <logger.hpp>
#include <calculator.hpp>
int main() {
// use both the logger and the calculator
}
The result of the expansion will be as follows:
// implementation of logger
// implementation of logger
// implementation of calculator
int main() {
// use both the logger and the calculator
}
As we can see, the logger has been added in the resulting file twice:
- It was added the first time because we included logger.hpp in the main.cpp file
- It was added the second time because we included calculator.hpp, which then includes logger.hpp
Included files that are not directly specified in a #include directive in the file we are compiling, but are instead included by some other included file, are called transitive included files.
Often, including the same header file multiple times creates a problem with multiple definitions, as we will see in Lesson 2, Functions, and the Lesson 03, Classes.
Including th...