In AI infrastructure and quantitative trading, performance is not just an optimization—it is a competitive advantage. Writing efficient systems requires understanding how software interacts with memory, hardware, and execution at a low level.

C++ is one of the most important languages for building this foundation. It offers fine-grained control over memory, predictable performance, and the ability to create high-performance abstractions without sacrificing efficiency.

For experienced programmers, a good starting point is A Tour of C++ by Bjarne Stroustrup, the creator of the language. It provides a concise, practical overview of modern C++, serving as a high-level map without unnecessary detail.

The Basics

Here is a program that writes Hello, World!:

#include <iostream>

int main()
{
    std::cout << "Hello, World!\n";
}

From Source Code to Executable

Although this program looks tiny, several important steps happen before it can run.

1. Preprocessing

The line

#include <iostream>

tells the preprocessor to include the standard input/output stream header.

This header provides the declarations needed to use std::cout, which sends output to the screen.

Before the compiler actually compiles your C++ program, the preprocessor runs first.

When it sees #include <iostream>, it roughly takes the contents of the iostream header and pastes them into your file at that point.

So the compiler effectively works with something like this:

// contents of iostream pasted here

int main()
{
    std::cout << "Hello, World!\n";
}

This matters because std::cout is declared in the standard library headers. Without including <iostream>, the compiler would not know what std::cout is, so the program would fail to compile.

After preprocessing, the compiler no longer sees #include <iostream> as a special instruction. Instead, it sees the expanded source code with the necessary declarations inserted.

More Preprocessing Examples

The preprocessor does more than just handle #include. It also processes macros and conditional compilation.

Example 1: Macro Substitution
#define SIZE 10

int arr[SIZE];

A simple mental model is that the preprocessor replaces SIZE with 10 before compilation, so the compiler roughly sees:

int arr[10];
Example 2: Function-Like Macro
#define SQUARE(x) ((x) * (x))

int y = SQUARE(5);

After preprocessing, this becomes roughly:

int y = ((5) * (5));
Example 3: Conditional Compilation
#define DEBUG

#ifdef DEBUG
std::cout << "Debug mode\n";
#endif

If DEBUG is defined, the preprocessor keeps that line. If it is not defined, the line is removed before compilation.

Example 4: Header Guards

A common use of the preprocessor is preventing the same header from being included multiple times.

#ifndef MY_HEADER_H
#define MY_HEADER_H

void f();

#endif

This pattern is called a header guard.

It tells the preprocessor to include the contents of the header only once, avoiding duplicate declarations.

2. Compilation

Next, the compiler translates the C++ source code into object code.

At this stage, the compiler checks the syntax and semantics of the program. It verifies things such as:

  • whether main is written correctly
  • whether std::cout has been declared
  • whether the operators are being used in a valid way

The result is usually an object file, not yet a runnable program.

You can think of an object file as a partially completed machine-level translation of your source code.

3. Linking

After compilation, the linker takes over.

The linker combines your object file with the other pieces required to form a complete program. These pieces often include code from the C++ standard library and runtime support provided by the system.

This step matters because seeing a declaration is not the same as having the actual implementation.

For example, the compiler may accept your use of std::cout because it knows the declaration from <iostream>, but the final executable still needs the underlying compiled library code that makes output actually work.

The linker resolves those references and joins everything together into one finished program.

A useful mental model is:

  • the compiler checks your code and translates it
  • the linker connects your translated code with all the other compiled pieces it depends on

4. Creating the Executable

Once linking succeeds, the result is an executable.

An executable is the file that the operating system can load into memory and run.

So the journey looks roughly like this:

source file -> preprocessor -> compiler -> object file -> linker -> executable

When you run that executable, the operating system starts the program, execution enters main(), and the statement

std::cout << "Hello, World!\n";

writes the text to standard output.

Summary

To get from source code to a running program, you need to understand the pipeline:

  • the preprocessor prepares the source code
  • the compiler translates it into object code
  • the linker combines everything into an executable
  • the operating system loads and runs that executable

This flow becomes increasingly important in larger systems, especially in performance-sensitive domains like AI infrastructure and quantitative trading, where build systems, libraries, binaries, and runtime behavior all matter.