How a C++ Program is Compiled and Run
You already ran a program
In the last lesson you saw your first C++ program and pressed Run. Something appeared on the screen. But what actually happened between those two moments?
It turns out “pressing Run” is not one step. It’s several, each handled by a different tool. Understanding those steps will make error messages less mysterious and give you a clearer picture of what C++ actually is.
The big picture
Your code is initially written in a text file with a .cpp extension. It goes through three stages before it becomes a running program:
- The preprocessor prepares your source code
- The compiler translates it into machine instructions
- The linker assembles the final program
Let’s walk through each one.
Stage 1: The preprocessor
The preprocessor is the first tool that touches your code. Its job is to look for lines that start with # and handle them before anything else happens.
You’ve already seen one:
#include <iostream>When the preprocessor sees this line, it finds the file named iostream and copies its entire contents into your code right at that spot. By the time it’s done, your file is much longer than you wrote. All the definitions needed to make std::cout work are now present.
Stage 2: The compiler
After the preprocessor finishes, the compiler takes over.
The compiler reads your code and translates it into machine code: the raw instructions your CPU actually understands. Your source code is human-readable text. Machine code is not. It’s a sequence of numbers that tell the processor exactly what to do, step by step.
Stage 3: The linker
The compiler alone doesn’t produce a runnable program. It produces an intermediate .o file (called an object file) that still has some gaps. The linker’s job is to fill those gaps and produce the final result.
For example, when you write std::cout, the actual code that makes output work is not something you wrote yourself. It lives in the standard library that ships with C++. The linker finds that code and connects it to your program.
For the small programs you’re writing now, this all happens invisibly. But knowing that the linker exists helps explain some obscure error messages. For example an error like “undefined reference” or “unresolved symbol” means a piece of code your program needs couldn’t be located.
The result
What comes out the other end is an executable: a file of machine code that your computer can run directly. On this platform, pressing Run handles all three stages automatically.
C++ compilation pipeline
Two kinds of errors
This is one of the most useful things to understand early, because it changes how you read error messages.
1. Compile-time errors
Compile-time errors are caught by the compiler before your program ever runs. The compiler read your code, couldn’t make sense of it, and refused to go further. A missing semicolon, a misspelled name, using something you haven’t defined yet: these all produce compile-time errors. The compiler will give you an error message typically with a line number to help you identify the source of the problem.
Try it yourself. We took the program from the last lesson and removed the semicolon after return 0 on line 5:
Press “Run” and you’ll see the program didn’t run at all. The compiler caught the problem first and told you exactly where to look.
2. Runtime errors
Runtime errors happen after compilation succeeded and the program is actually running. The code was valid enough for the compiler to accept, but something went wrong during execution.
For example, consider a program that divides a number by a value entered by the user. The code will compile fine, but if the user enters zero, the program will crash because dividing by zero is undefined. The compiler has no way to know what the user will type.
Runtime errors are generally harder to deal with. When the compiler rejects your code, you get an error message typically with a line number. When a program crashes while running, finding the cause takes more digging.